Search code examples
javajava-native-interfacedlopen

Calling dlopen from a shared library loaded via JNI makes previously loaded symbols invisible


I have a Java application which interacts with native code using JNI. The native code compiles a file at runtime and attempts to load this file using a dlopen call. This call fails and I get a warning stating

Could not load library (x):(x) undefined symbol: y

However when I have a native application starting a JVM via JNI run the same code, this error does not occur and it runs as expected. I am suspecting Java is doing something fancy which causes the already loaded libraries to be invisible for the library that is loaded with dlopen.

This I did to diagnose the problem:

  • Confirmed in which shared library the symbol that was supposedly undefined is located using objdump
  • Confirmed this library is loaded by using gdb (via eclipse - the library was listed in the modules pane)
  • Printed LD_LIBRARY_PATH just before the dlopen and confirmed Java passes it through (It did add Java's lib dirs but the original dirs were still there)

I have been trying to solve this for a while now, but I can't figure out what is going on. Especially because it does work when the JVM is loaded from a native application.

Thank you in advance!


Solution

  • I finally found the answer. The solution was to recompile the shared library that contained the symbol that was not found with the -Wl,--export-dynamic linker flag.

    Interestingly I did not program that shared library myself and I would expect the default compilation to add the flag since it was needed for software using it to function properly.

    Either way it is a open source project so I could compile it with the proper flags set.