Java версии 1.6 UnsatisfiedLinkError при загрузке общей библиотеки, Java 1.4 работает нормально?

Проблема решена. В libjnidiagnosticsserver.so отсутствовала библиотека компоновщика и путь к libfesdiagnosticsserver.so. Java 1.4 должна быть более либеральной в поиске неопределенных символов, чем Java 1.6. Спасибо за вашу помощь. Любые предложения по этикету для справедливого закрытия этого?

(Отказ от ответственности: новичок в Java)

Я написал приложение Java, которое использует JNI для вызова моей общей библиотеки C++. Он печатает версию Java и получает и печатает LD_LIBRARY_PATH при выполнении.

Java версии 1.4 - Все хорошо!:

/usr/bin/java -jar "javadiagnosticsserver-test.jar"
java version=1.4.2
LD_LIBRARY_PATH = /usr/lib/fesdiagnostics

Java версии 1.6 — UnsatisfiedLinkError:

"неопределенный символ" _ZN17DiagnosticsServerC1Ev определен в libfesdiagnosticsserver.so. Java 1.4 видит, Java 1.6 нет? Вызов System.loadLibrary("fesdiagnosticsserver") работает. Java 1.6 loadLibrary не знает где искать?

/usr/java/jdk1.6.0_26/bin/java -jar "javadiagnosticsserver-test.jar"
version=1.6.0_26
class path=javadiagnosticsserver-test.jar
os.arch=i386
sun.arch.data.model=32
$HOME = /home/esutton
$LD_LIBRARY_PATH = /usr/java/jdk1.6.0_26/jre/lib/i386/client:/usr/java/jdk1.6.0_26/jre/lib/i386:/usr/java/jdk1.6.0_26/jre/../lib/i386:/usr/lib/fesdiagnostics
Dbg: Loading native lib dependencies...
Dbg: System.loadLibrary("fesdiagnostics");
Dbg: loaded fesdiagnostics
Dbg: The undefined symbol _ZN17DiagnosticsServerC1Ev is in libfesdiagnosticsserver.so
Dbg: System.loadLibrary("fesdiagnosticsserver"); 
Dbg: loaded fesdiagnosticsserver
Dbg: System.loadLibrary("jnidiagnosticsserver");
Exception in thread "main" java.lang.UnsatisfiedLinkError: /usr/lib/fesdiagnostics/libjnidiagnosticsserver.so: /usr/lib/fesdiagnostics/libjnidiagnosticsserver.so: undefined symbol: _ZN17DiagnosticsServerC1Ev
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1807)
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1732)
        at java.lang.Runtime.loadLibrary0(Runtime.java:823)
        at java.lang.System.loadLibrary(System.java:1028)
        at fes.JniDiagnostics.libLoad(JniDiagnostics.java:30)
        at fes.JniDiagnostics.<clinit>(JniDiagnostics.java:38)
        at fes.FesDiagnostics.<clinit>(FesDiagnostics.java:17)
        at javadiagnosticsservertest.Main.main(Main.java:37)

Среда одинакова в обоих случаях:

LD_LIBRARY_PATH =/usr/lib/fesdiagnostics
PATH = /opt/ActivePython-2.7/bin:/usr/java/jdk1.6.0_26/bin: \
/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin: \
/sbin:/opt/qtsdk-2010.01/qt/bin:/home/esutton/bin:/sbin: \
/opt/qtsdk-2010.01/qt/bin
JAVA_HOME = /usr/java/jdk1.6.0_26

Параметры компиляции Native C++ Shared Lib:

g++ -Wl,-rpath,/opt/qtsdk-2010.01/qt/lib -shared \
-Wl,-soname,libjnidiagnosticsserver.so.1 \
-o libjnidiagnosticsserver.so.1.0.0 build/Debug/GNU-Linux-x86/ \ 
jnifesdiagnostics.o -L/opt/qtsdk-2010.01/qt/lib -lQtGui \
-L/opt/qtsdk-2010.01/qt/lib -L/usr/X11R6/lib -lQtCore -lpthread
ln -s libjnidiagnosticsserver.so.1.0.0 libjnidiagnosticsserver.so
ln -s libjnidiagnosticsserver.so.1.0.0 libjnidiagnosticsserver.so.1
ln -s libjnidiagnosticsserver.so.1.0.0 libjnidiagnosticsserver.so.1.0
rm -f dist/libjnidiagnosticsserver.so.1.0.0
rm -f dist/libjnidiagnosticsserver.so
rm -f dist/libjnidiagnosticsserver.so.1
rm -f dist/libjnidiagnosticsserver.so.1.0
mv -f libjnidiagnosticsserver.so.1.0.0 libjnidiagnosticsserver.so \
\libjnidiagnosticsserver.so.1 libjnidiagnosticsserver.so.1.0 dist/

Когда он работает под Java 1.4, я должен сначала загрузить зависимости jnidiagnosticsserver. Я не понимаю почему. Я ожидал, что LD_LIBRARY_PATH позаботится об этом:

public class JniDiagnostics {

    public native void open(String configurationFile);

    public native void close();

    public native String query(String restfulQueryString);
    private static String[] libraryDependencyList = {"fesdiagnostics", "fesdiagnosticsserver", "jnidiagnosticsserver"};

    private static void libLoad(String libName) {
        System.out.println("Dbg: System.loadLibrary(\"" + libName + "\");");
        System.loadLibrary(libName);
        System.out.println("Dbg: loaded " + libName);
    }

    static //static initializer code
    {
        System.out.println("Dbg: Loading native lib dependencies...");
        for (int i = 0; i < libraryDependencyList.length; i++) {
            libLoad(libraryDependencyList[i]);

        }
    }
}

Проблема безопасности? Проблема с настройкой версии Java?

Заранее спасибо за любое направление,

-Ed

CentOS 5.2 32-bit
Netbeans 6.9.1
Java version 1.6.0_26

PS: Моя цель - заставить мой исходный код Java работать в веб-службе Glassfish RESTful. Если LD_LIBRARY_PATH можно решить для java-приложения, я надеюсь, что такое же решение будет применяться в Glassfish 3.


person Ed of the Mountain    schedule 21.02.2012    source источник
comment
Вы можете попробовать запустить виртуальную машину java -Djava.library.path=/usr/lib/fesdiagnostics ...   -  person stacker    schedule 21.02.2012
comment
Спасибо штабелер за быстрый ответ. Добавление java.library.path, похоже, не влияет: /usr/java/jdk1.6.0_26/bin/java -Djava.library.path=/usr/lib/fesdiagnostics -jar javadiagnosticsserver-test.jar   -  person Ed of the Mountain    schedule 21.02.2012
comment
@Ed.: Вы компилируете библиотеку C++ с какими-либо параметрами?   -  person Cratylus    schedule 21.02.2012
comment
Общая библиотека C++ отлично работает под Java версии 1.4. Существуют ли параметры С++, которые могут повлиять на версию Java 1.6, но не на 1.4?   -  person Ed of the Mountain    schedule 21.02.2012
comment
@Ed.: Может быть. Почему бы вам не обновить OP, указав, как вы создаете библиотеку C ++?   -  person Cratylus    schedule 21.02.2012
comment
Я вставил параметры компиляции собственной библиотеки С++ в вопрос выше.   -  person Ed of the Mountain    schedule 21.02.2012
comment
Я также добавил команды компоновщика к командам C++ в OP.   -  person Ed of the Mountain    schedule 21.02.2012
comment
Вы используете разные .so файлы, верно? Похоже, что определение рассматриваемого символа (конструктор DiagnosticsServer::DiagnosticsServer()) каким-то образом не попало в .so. Не могли бы вы проверить вывод компилятора C++ на наличие сообщений об ошибках, связанных с файлом, в котором он должен быть определен?   -  person Joni    schedule 21.02.2012
comment
Проблема решена. В libjnidiagnosticsserver.so отсутствовала библиотека компоновщика и путь к libfesdiagnosticsserver.so. Java 1.4 должна быть более либеральной в поиске неопределенных символов, чем Java 1.6. Спасибо за вашу помощь. Любые предложения по этикету для справедливого закрытия этого?   -  person Ed of the Mountain    schedule 22.02.2012


Ответы (1)


Я предполагаю, что проблема заключается в отсутствии зависимости от вашей общей библиотеки. Попробуйте запустить следующую команду, чтобы выяснить это:

ldd -d -r /home/esutton/jnidiagnosticsserver/dist/libjnidiagnosticsserver.so.1.0.0

Это показывает отсутствующие символы.

UnsatisfiedLinkError документируется как:

Thrown if the Java Virtual Machine cannot find an appropriate 
native-language definition of a method declared native. 
person phlogratos    schedule 21.02.2012
comment
Спасибо, но он отлично работает с Java версии 1.4, но не с Java версии 1.6, поэтому отсутствует недостающая зависимость. - person Ed of the Mountain; 21.02.2012
comment
Запуск ldd ./libjnidiagnosticsserver.so и запуск ldd /usr/lib/fesdiagnostics/libfesdiagnostics.so приводит к нулевому количеству сообщений о том, что не найдено. - person Ed of the Mountain; 21.02.2012
comment
Пожалуйста, добавьте переключатель -d для более подробной информации. - person phlogratos; 21.02.2012
comment
Есть ли пробелы в LD_LIBRARY_PATh после двоеточий? - person phlogratos; 21.02.2012
comment
Нет пробелов. Я пробовал ldd -d, кажется, меняет отображаемые адреса, но я не вижу пропущенных символов или не найденных сообщений. Как это может быть проблемой зависимости, если он работает под Java версии 1.4? - person Ed of the Mountain; 21.02.2012
comment
Вывод показывает другой LD_LIBRARY_PATH при запуске на Java 1.6. - person phlogratos; 21.02.2012
comment
Да, LD_LIBRARY_PATH в Java 1.6 отличается. Java 1.6, по-видимому, предваряет кучу вещей JDK. - person Ed of the Mountain; 22.02.2012
comment
Да, я согласен, что это UnsatisfiedLinkError. Я согласен, что отсутствуют символы, как подтверждает ldd -d -r. Символы находятся в зависимой общей библиотеке. Java 1.4 находит их без проблем, Java 1.6 — нет. В любом случае, я заменяю вызовы System.load(\absolute\path\to\libmyshared.so) вызовами System.loadLibrary(myshared). Не уверен, что я что-то получаю, поскольку, хотя он работает под Java 1.4, он все еще не работает под Java 1.6. - person Ed of the Mountain; 22.02.2012
comment
давайте продолжим это обсуждение в чате - person Ed of the Mountain; 22.02.2012