Matlab не может видеть некоторые из моих классов java (не всех) в пакете jar

У меня есть проблема, которая сводит меня с ума. Matlab видит только некоторые из моих классов, встроенных в файл JAR

Если я скомпилирую классы вне пакета и добавлю путь к классу в Matlab, используя javaaddpath, у меня не возникнет никаких проблем

Когда я компилирую класс в пакете и затем пытаюсь получить к ним доступ в Matlab, у меня возникают проблемы. Ниже немного кода Matlab

>>javaaddpath('/Users/me/Documents/workspace/EKGTest.jar');
>>clear java
>>import com.neurosky.thinkgear.*
>>methods('EkgSense')

Methods for class com.neurosky.thinkgear.EkgSense:

EkgSense                  getClass                  notify                    reset            
addTemplate               getClassificationResults  notifyAll                  toString
equals                    hashCode                  processData               wait   

>>methods('EkgEpoch')

No methods for class EkgEpoch or no class EkgEpoch

Сейчас я смотрю в пакете, все классы общедоступны. Это результат jar -tf

osx:/Users/me/Documents/workspace> jar tf EKGTest.jar
META-INF/MANIFEST.MF
META-INF/REFACTORINGS.XML
com/
com/neurosky/
com/neurosky/thinkgear/
com/neurosky/thinkgear/EkgEpoch.class
com/neurosky/thinkgear/EkgEpoch.java
com/neurosky/thinkgear/EkgParameters.class
com/neurosky/thinkgear/EkgParameters.java
com/neurosky/thinkgear/EkgTemplate.class
com/neurosky/thinkgear/EkgTemplate.java
com/neurosky/thinkgear/Matlab.class
com/neurosky/thinkgear/Matlab.java
com/neurosky/thinkgear/EkgSense.class
com/neurosky/thinkgear/EkgSense.java
com/neurosky/thinkgear/DistanceArray.class
com/neurosky/thinkgear/DistanceArray.java

и ниже javap --classpath

osx:/Users/me/Documents/workspace> javap -classpath /Users/me/Documents/workspace/EKGTest.jar    com.neurosky.thinkgear.EkgEpoch
Compiled from "EkgEpoch.java"
public class com.neurosky.thinkgear.EkgEpoch extends java.lang.Object implements java.lang.Cloneable{
    public int numberOfSamples;
    public float[] data;
    public com.neurosky.thinkgear.EkgEpoch(int);
    public com.neurosky.thinkgear.EkgEpoch(int, float[]);
    public com.neurosky.thinkgear.EkgEpoch(float[]);
    public com.neurosky.thinkgear.EkgEpoch(com.neurosky.thinkgear.EkgEpoch);
    public com.neurosky.thinkgear.EkgEpoch(org.json.JSONArray);
    public org.json.JSONArray toJSONArray();
    public static float[] convolve(float[], float[]);
    public float getLineNoiseAmplitude();
    public com.neurosky.thinkgear.EkgEpoch subtract(com.neurosky.thinkgear.EkgEpoch);
    public com.neurosky.thinkgear.EkgEpoch subEpoch(int, int);
    public com.neurosky.thinkgear.EkgEpoch square();
    public com.neurosky.thinkgear.EkgEpoch subtract(float);
    public com.neurosky.thinkgear.EkgEpoch diff();
    public boolean exceedValue(float, int, int);
    public com.neurosky.thinkgear.EkgEpoch smooth(int);
    public float mean();
    public float sum();
    public float max();
    public float median();
    public com.neurosky.thinkgear.EkgEpoch clone();
    public com.neurosky.thinkgear.EkgEpoch sort();
    public int[] sortIndices(com.neurosky.thinkgear.EkgEpoch);
    public float std();
    public int find_heart_beats(int[], float);
    public com.neurosky.thinkgear.EkgEpoch detrend();
    public java.lang.Object clone()       throws java.lang.CloneNotSupportedException;
}

osx:/Users/me/Documents/workspace> javap -classpath /Users/me/Documents/workspace/EKGTest.jar  com.neurosky.thinkgear.EkgSense
Compiled from "EkgSense.java"
public class com.neurosky.thinkgear.EkgSense extends java.lang.Object{
    public com.neurosky.thinkgear.EkgParameters params;
    public com.neurosky.thinkgear.EkgTemplate[] templates;
    public com.neurosky.thinkgear.EkgTemplate currentData;
    public int lastTemplateInd;
    public float lastEpochValue;
    public com.neurosky.thinkgear.EkgSense(com.neurosky.thinkgear.EkgParameters);
    public void reset();
    public void addTemplate(java.lang.String, float[][]);
    public void addTemplate(com.neurosky.thinkgear.EkgTemplate);
    public java.lang.String getClassificationResults();
    public boolean processData(float[]);
}

Я использую Matlab на OSX. Я пытался с Matlab 7.7.0.471 (R2008b) и 7.11.0.584 (R2010b) и получил ту же проблему. Оба Matlab используют нативный OSX Java (Java 1.6.0_26-b03-384-10M3425 с Apple Inc. Java HotSpot (TM) 64-битный сервер, смешанный режим виртуальной машины), который должен быть таким же, как в Eclipse (я проверил и Eclipse компилируется с 1.6).

Помните, что у меня нет проблем с отсутствующим классом, когда я удаляю инструкцию package и некоторые операции импорта в верхней части java файлов (конечно же, во всех классах) и когда я просто добавляю путь к файлам .class (не обращаюсь к ним) в файле JAR).

Любая помощь будет принята с благодарностью. Спасибо,

Джейсон

Ответ 1

В конце концов я обнаружил проблему, которую нельзя увидеть выше. Проблема (нигде не документированная) заключалась в том, что некоторые из моих классов используют внешние пакеты, которые я не импортировал в Matlab. Я не планировал использовать какие-либо функции, связанные с этими пакетами.

Тем не менее, сообщение об ошибке Matlab, что он не может найти класс, озадачивает. Сообщение об ошибке, указывающее, что класс не может использоваться, потому что на некоторые пакеты не ссылаются, было бы наиболее полезным.

Если ваш пакет использует внешние пакеты, обязательно включите все соответствующие файлы jar в путь к классам java, иначе Matlab не увидит ваши зависимые классы.

Еще один совет, который я нашел полезным, заключается в том, что функция Matlab "import" не будет возвращать ошибку, если вы введете несуществующий пакет, например import java.doesnotexist.* Работает нормально. Однако import java.doesnotexist.aclass не будет работать.

Джейсон

Ответ 2

Другая причина, по которой MATLAB не увидит класс, заключается в компиляции для JRE7 и использовании MATLAB 2012b (вероятно, относится к другим выпускам MATLAB).

Симтом - чрезвычайно хромая ошибка

The class "JavaNuServer" is undefined.
Perhaps Java is not running.

Решение:

Компиляция с флагами javac

-source 1.6 -target 1.6 

Ответ 3

В дополнение к принятому ответу - гораздо лучший способ проверить, правильно ли загружен класс java, чем через команду import. Используйте whereisjavaclassloadingfrom функцию, предоставленную Andrew Janke в этом ответе.

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

Ответ 4

Эта же проблема может быть вызвана несколькими типами сбоев. (Все они разочаровывают, так как у вас нет НИКАКИХ сведений о том, что не удалось!) В принятом ответе описывается одна причина и решение. Ответ Wolfgang Kuehn получил еще одну возможную проблему, хотя мне было трудно понять суть, поэтому я решил написать свой собственный ответ, расширяющийся на нем несколько более широко:

Каждая версия Matlab поставляется с определенной JRE, которая запускается и поддерживается. Разная версия корабля Matlab с разной версией JRE. Неважно, какая у вас версия Matlab и связанная с ней JRE, если вы выполнили свои внешние классы Java, которые находятся в файле jar с более высокой (и несовместимой) версией компилятора Java, Matlab откажется признать классы, даже если они находятся в банку. Если вам повезет, вы можете исправить это, перекомпилировав Java с флагом, определяющим совместимость с версией Java в вашем экземпляре Matlab.

Чтобы узнать, какая версия Java работает в Matlab, используйте эту команду в командной строке Matlab:

version -java

Ответ 6

Еще одна причина, по которой это происходит, заключается в том, что некоторые классы должны находиться в статическом пути к классам Matlab.

В этом случае один из моих классов java отлично работал в Matlab2017b после добавления большего количества jar файлов в динамический путь к классу через javaaddpath, как предложено выше. Это предотвратило исключение java.lang.ClassNotFoundException.

Тот же подход потерпел неудачу в Matlab2019a.

Теперь я решил, что моя проблема решена простым добавлением моего jar файла 'uber', содержащего все jar файлы, которые нужны моему приложению, в файл classpath.txt, например, так:

   # DO NOT MODIFY THIS FILE.  IT IS AN AUTOGENERATED FILE.

/Users/andyhueni/Desktop/SPECCHIO_new_build2/SPECCHIO.app/Contents/Java/specchio-client.jar

$matlabroot/java/patch
$matlabroot/java/jar/jmi.jar
...

Расположение в classpath.txt (верх или конец файла), по-видимому, не имеет значения.

Изменение classpath.txt может быть недоступно для всех пользователей, но есть способы обхода, перечисленные в этом превосходном источнике информации: https://undocumentedmatlab.com/blog/static-java-classpath-hacks