Search code examples
javajava-native-interfaceshared-librariesstatic-librariesstatic-linking

JNI duplicate library loading on Mac OS X crashes


I have two shared libraries A.dylib and B.dylib which are both linked with the static library S.a

When I only load A.dylib with System.load or System.loadLibrary, there is no problem. And this is same for the B.dylib too.

But when I load one after the other (the order does not matter), I see that the second loaded library crashes on some initialization code. And when I check the stack, the crashing code block is somewhere in S.a

Somehow S.a symbols are being shared between A.dylib and B.dylib when they are both loaded. And this only happens in Mac OS X. The stack clearly shows that the second loaded one invokes a method of S.a via the first loaded one. To be more clear;

  • Load A.dylib
  • A#init -> invokes a method from statically linked S.a
  • Load B.dylib
  • B#init -> invokes a method from statically linked S.a via A.dylib

I tried to load A.dylib and B.dylib in different class loaders but this did not change the result. Do you know if there is a way to prevent this sharing?


Solution

  • Well I found the solution,

    The problem was as I guessed the static libraries were exposing their symbols by default so at the end there was a name conflict because of duplicate symbols.

    While linking the dynamic libs I set the linker flag -exported_symbols_list with an input text file which includes only the exposed symbols. In my case, those are only JNI tier methods; _Java_package_methodName _JNI_OnLoad _JNI_OnUnload

    -exported_symbols_list only exports the symbols listed in the input file. The rest is hidden and as a result I have no duplicate symbols.

    I don't know why it does not happen on Linux and Windows though.