Pergunta

Problem solved. libjnidiagnosticsserver.so was missing linker lib and path to libfesdiagnosticsserver.so. Java 1.4 must be more liberal on locating undefined symbols than Java 1.6. Thank you all for your help. Any suggestions on etiquette for closing this equitably?

( Disclaimer: Java newbie )

I wrote a Java application that uses JNI to call my C++ shared library. It prints java version and gets and prints LD_LIBRARY_PATH when executed.

Java version 1.4 - All is good!:

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

Java version 1.6 - UnsatisfiedLinkError:

The "undefined symbol" _ZN17DiagnosticsServerC1Ev is defined in libfesdiagnosticsserver.so. Java 1.4 sees it, Java 1.6 does not? The System.loadLibrary("fesdiagnosticsserver") call works. Java 1.6 loadLibrary does not know where to look?

/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)

The environment is the same in both cases:

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 Compile Options:

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/

When it works under Java 1.4 I must load the dependencies of jnidiagnosticsserver first. I do not understand why. I expected that LD_LIBRARY_PATH would have taken care of this:

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]);

        }
    }
}

Security issue? Java version configuration issue?

Thanks in advance for any direction,

-Ed

CentOS 5.2 32-bit
Netbeans 6.9.1
Java version 1.6.0_26

PS: My goal is to get my Java source to run in a Glassfish RESTful web service. If LD_LIBRARY_PATH can be solved for a java app, I am hoping the same solution will apply under Glassfish 3.

Foi útil?

Solução

I guess the problem is a missig dependency of your shared library. Try running the following command to figure this out:

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

This shows missing symbols.

UnsatisfiedLinkError is documented as:

Thrown if the Java Virtual Machine cannot find an appropriate 
native-language definition of a method declared native. 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top