Search code examples
javatomcatnoclassdeffounderrorjna

jna Native.LoadLibrary does not manage to load library on server (working in local)


I use JNA to load a c++ library (.so) in a java project. I package my library inside the jar, and load it from the jar when instantiating the java class that uses it. I do all this like so:

  • mvn install compiles the c++ code and packages the outcome dynamic library inside the jar.
  • I call in a static context when instantiating the LibraryWrapperClass the following

    System.load( temp.getAbsolutePath() );
    

where temp is a temporary file containing the library which was found in the jar. This code is based on the work found here adamheinrich - I call Native.loadLibrary(LIBRARYPATH) to wrap the library into a java class.

    private interface Wrapper extends Library {
        Wrapper INSTANCE = Native.loadLibrary( C_LIBRARY_PATH, Wrapper.class );

        Pointer Constructor();
        ...
    }
  • I run tests and validate that the library was found and up and running.
  • I use a java web project that depends on this project. It uses tomcat and runs fine in local.

My issue is that when I deploy on the server, the LibraryWrapperClass cannot instantiate. Error on server is:

java.lang.NoClassDefFoundError: Could not initialize class pacakgeName.LibraryWrapperClass
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:375)
    at org.hibernate.annotations.common.util.StandardClassLoaderDelegateImpl.classForName(StandardClassLoaderDelegateImpl.java:57)
    at org.hibernate.boot.internal.MetadataBuilderImpl$MetadataBuildingOptionsImpl$4.classForName(MetadataBuilderImpl.java:758)
    at org.hibernate.annotations.common.reflection.java.JavaReflectionManager.classForName(JavaReflectionManager.java:144)
    at... 

This error seems that the library is found, since there is not the UnsatisfiedLinkError exception thrown. But something else is failing. Do someone know what could happen? How could I debug?

I recall that everything works perfectly in local.


Solution

  • How could I debug?

    1. with strace

    strace will give you what files Tomcat is trying to open : strace -f -e trace=file -o log.txt bin/startup.sh

    After this, look for packageName in log.txt, or other files not found with :

    egrep ' open.*No such file' log.txt
    

    2. with JConsole

    Enable JMX, launch a JConsole, go to VM summary tab, and check/compare very carefully VM arguments/classpath/library path/boot class path

    3. dependency listing with ldd

    If a dependency issue is likely to be the problem, the ldd sharedLibraryFile.so command lists all the dependencies and allows to track which one might be missing.