ClassNotFoundException с использованием PApplet от Processing с помощью Arduino Tool

Я разрабатываю базовый PApplet Processing для запуска в качестве инструмента в Arduino IDE, и это работало нормально до версии Arduino 1.5.8. У меня проблема в том, что в Arduino 1.6.0 часть кода подверглась рефакторингу, и это произошло на стороне Arduino:

" Чтобы обеспечить лучшую командную строку, IDE была реорганизована в приложение и arduino-core, который является старым ядром. Чтобы избежать конфликтов между классами, PApplet был перемещен с processing.core.PApplet на processing.app.legacy.PApplet "

Это объяснение пришло от одного из разработчиков Arduino IDE. Стоит отметить, что processing.app.legacy.PApplet — это (очень) урезанная версия PApplet, в которой отброшены все графические возможности, которые мне нужны.

Первоначально я получал эту ошибку:

Uncaught exception in main method: java.lang.NoClassDefFoundError: processing/core/PApplet

Размещение файла core.jar Processing в том же месте, что и файл jar экспортированного инструмента eclipse, устранило эту проблему, но разрешил другому:

Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: You need to use "Import Library" to add processing.core.PGraphicsJava2D to your sketch.
    at processing.core.PApplet.makeGraphics(Unknown Source)
    at processing.core.PApplet.init(Unknown Source)

Что сбивает с толку, так это то, что я использовал исходные java-файлы библиотеки Processing вместо скомпилированной библиотеки core.jar, чтобы избежать этой проблемы, но это ничего не изменило.

Я просмотрел исходный код PApplet и обнаружил, что класс графики/рендерера загружается и создается во время выполнения здесь вот так:

Class<?> rendererClass =
        Thread.currentThread().getContextClassLoader().loadClass(renderer);

      Constructor<?> constructor = rendererClass.getConstructor(new Class[] { });
      PGraphics pg = (PGraphics) constructor.newInstance();

и здесь исключение ClassNotFoundException выдает исключение Runtime:

catch (ClassNotFoundException cnfe) {
//      if (cnfe.getMessage().indexOf("processing.opengl.PGraphicsOpenGL") != -1) {
//        throw new RuntimeException(openglError +
//                                   " (The library .jar file is missing.)");
//      } else {
      if (external) {
        throw new RuntimeException("You need to use \"Import Library\" " +
                                   "to add " + renderer + " to your sketch.");
      } else {
        throw new RuntimeException("The " + renderer +
                                   " renderer is not in the class path.");
      }

    }

Я освоился с java, но у меня недостаточно опыта, чтобы понять это. Это похоже на проблему с путем к классам, но я не уверен, почему это происходит и как я должен сообщить java, где найти классы, которые ему нужно загрузить.

Вот тест кода, который я использую на основе примера Arduino Tool, который поставляется с IDE. В настоящее время я экспортирую файл jar (не запускаемый) из eclipse:

/*
  Part of the Processing project - http://processing.org

  Copyright (c) 2008 Ben Fry and Casey Reas

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation,
  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package com.transformers.supermangletron;


import java.awt.Color;
import java.awt.Dimension;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import processing.core.PApplet;
import processing.app.Editor;
import processing.app.tools.Tool;
//import processing.app.legacy.PApplet;

/**
 * Example Tools menu entry.
 */
public class Mangler implements Tool {
  private Editor editor;

  public void init(Editor editor) {
    this.editor = editor;
  }

  private void setupSketch(){
    int w = 255;
    int h = 255;

//      PApplet ui = new PApplet();
    TestApp ui = new TestApp();

      JFrame window = new JFrame(getMenuTitle());
      window.setPreferredSize(new Dimension(w,h+20));

    window.add(ui);
      window.invalidate();
      window.pack();
      window.setVisible(true);
      window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      ui.init();

    System.out.println("setup complete");
  }

  public String getMenuTitle() {
    return "Mangle Selection";
  }


  public void run() {
      setupSketch();
  }

}

и вот базовый тестовый апплет, который я пытаюсь отобразить:

package com.transformers.supermangletron;

import processing.core.PApplet;

public class TestApp extends PApplet {
    public void setup(){
        size(100,100);
    }
    public void draw(){
        background((1.0f+sin(frameCount * .01f)) * 127);
    }
}

Как я могу исправить это ClassNotFoundException с моей настройкой? Любые намеки на то, что я должен дважды проверить в отношении путей к классам?


person George Profenza    schedule 20.02.2015    source источник


Ответы (1)


Если вы получаете эту ошибку при запуске из eclipse, вы должны добавить библиотеки jar в свой путь к классам. Вы делаете это, щелкнув правой кнопкой мыши свой проект, перейдя к свойствам, а затем к пути сборки Java. Убедитесь, что библиотеки jar перечислены на вкладке «Библиотеки».

Если вы получаете эту ошибку при запуске экспортированного jar-файла, вам нужно сделать одно из двух:

Либо убедитесь, что вы экспортируете исполняемый jar-файл с библиотечными jar-файлами, встроенными внутрь основного jar-файла. Сделайте это из eclipse, щелкнув проект правой кнопкой мыши, выбрав «Экспорт», затем выбрав «runnable jar» из списка.

Или убедитесь, что вы установили путь к классам в качестве аргумента JVM. Вы делаете это, используя опцию -cp из командной строки.

person Kevin Workman    schedule 20.02.2015
comment
Привет, Кевин, к сожалению, в моем случае у меня мало ограничений. Раньше, когда я использовал core.jar от Processing, я убедился, что библиотека добавлена ​​в путь сборки (и указана на вкладке «Библиотеки»). Теперь я использую исходный код библиотеки по тому же исходному пути, что и мои два тестовых класса. Нужно ли мне делать что-то дополнительно? Что касается runnable jar, это не относится. Я создаю инструмент Arduino, который, по сути, реализует интерфейс. Это вызывается Arduino IDE, поэтому в реализации инструмента нет точки main()/entry... - person George Profenza; 20.02.2015
comment
... Как и выше, поскольку инструмент создается/создается средой Arduino IDE, насколько я могу судить, у меня нет никакого контроля над аргументами командной строки (такими как -cp). Можете ли вы назвать другие причины, по которым эти классы не могут быть найдены во время выполнения? - person George Profenza; 20.02.2015
comment
Я не уверен, что понимаю - что вы имеете в виду, когда говорите, что используете исходный код библиотеки? Основной ответ на ваш вопрос заключается в том, что вам нужно либо включить библиотечные банки внутри вашей основной банки, либо установить их в качестве пути к классам в качестве аргумента. Что вы выберете и как вы это сделаете, полностью зависит от ваших настроек. - person Kevin Workman; 20.02.2015
comment
Используя исходный код библиотеки, я имею в виду, что скопировал Processing 1.5. .1 исходные файлы основной библиотеки java в папку src моего проекта eclipse - person George Profenza; 20.02.2015
comment
После двойной проверки того, что core.jar находится на вкладке «Библиотеки» в настройках «Путь сборки» проекта, у меня возникла паранойя, что классы каким-то образом не видны, поэтому я напрямую использовал нескомпилированные классы Java. Я все еще получаю ClassNotFoundException, хотя я действительно не понимаю. Этого не должно произойти, если я использую исходные файлы, верно? Эти классы в конечном итоге будут заархивированы вместе с остальным кодом в экспортированном банке, верно? - person George Profenza; 20.02.2015
comment
Ну видимо не они. Вы уверены, что они правильно компилируются? Я действительно не стал бы использовать такой источник. Сохраните исходный код в отдельном проекте или просто используйте поставляемые jar-файлы библиотеки. - person Kevin Workman; 20.02.2015
comment
Я бы хотел, чтобы библиотека jar просто работала, но на данный момент я готов попробовать что угодно. Код компилируется правильно (иначе я не смог бы запустить код и увидеть исключения во время выполнения). Спасибо за предложения (+1), попробую любые другие, которые у вас могут быть. - person George Profenza; 20.02.2015
comment
Я бы настоятельно рекомендовал не включать такой источник. Вернитесь к обычной настройке, когда в вашем пути к классам есть библиотечные банки. Экспортируйте банку. Затем откройте банку в средстве просмотра архивов (например, winzip или 7zip) или используйте параметр -tf, чтобы увидеть, какие файлы находятся в банке. Этот класс расположен там, где он должен быть? - person Kevin Workman; 20.02.2015
comment
Привет, Кевин, я могу отказаться от попыток получить PApplet с графикой, хорошо воспроизводимой в новых версиях Arduino, и переписать его, чтобы удалить зависимости от PApplet. - person George Profenza; 24.07.2015