Mac OS X 上的 JNI 重复库加载崩溃
JNI duplicate library loading on Mac OS X crashes
我有两个共享库 A.dylib 和 B.dylib,它们都链接到静态库 S.a
当我只用System.load或System.load库加载A.dylib时,没有问题。 B.dylib 也是如此。
但是当我一个接一个地加载时(顺序无关紧要),我发现第二个加载的库在一些初始化代码上崩溃了。当我检查堆栈时,崩溃的代码块位于 S.a
中的某处
S.a 符号在 A.dylib 和 B.dylib 加载时以某种方式共享。而这只发生在 Mac OS X 中。堆栈清楚地表明,第二个加载的通过第一个加载的调用了 S.a 的方法。更清楚;
- 加载A.dylib
- A#init -> 从静态链接中调用方法 S.a
- 加载B.dylib
- B#init -> 通过 A.dylib
从静态链接的 S.a 调用一个方法
我尝试在不同的 class 加载器中加载 A.dylib 和 B.dylib 但这并没有改变结果。你知道有没有办法阻止这种分享?
好吧,我找到了解决方案,
问题出在我的猜测,静态库默认会公开它们的符号,所以最后由于重复的符号而导致名称冲突。
在链接动态库时,我将链接器标志 -exported_symbols_list 设置为输入文本文件,该文件仅包含公开的符号。就我而言,这些只是 JNI 层方法;
_Java_package_methodName
_JNI_OnLoad
_JNI_OnUnload
-exported_symbols_list 仅导出输入文件中列出的符号。其余的是隐藏的,因此我没有重复的符号。
我不知道为什么 Linux 和 Windows 上没有发生。
我有两个共享库 A.dylib 和 B.dylib,它们都链接到静态库 S.a
当我只用System.load或System.load库加载A.dylib时,没有问题。 B.dylib 也是如此。
但是当我一个接一个地加载时(顺序无关紧要),我发现第二个加载的库在一些初始化代码上崩溃了。当我检查堆栈时,崩溃的代码块位于 S.a
中的某处S.a 符号在 A.dylib 和 B.dylib 加载时以某种方式共享。而这只发生在 Mac OS X 中。堆栈清楚地表明,第二个加载的通过第一个加载的调用了 S.a 的方法。更清楚;
- 加载A.dylib
- A#init -> 从静态链接中调用方法 S.a
- 加载B.dylib
- B#init -> 通过 A.dylib 从静态链接的 S.a 调用一个方法
我尝试在不同的 class 加载器中加载 A.dylib 和 B.dylib 但这并没有改变结果。你知道有没有办法阻止这种分享?
好吧,我找到了解决方案,
问题出在我的猜测,静态库默认会公开它们的符号,所以最后由于重复的符号而导致名称冲突。
在链接动态库时,我将链接器标志 -exported_symbols_list 设置为输入文本文件,该文件仅包含公开的符号。就我而言,这些只是 JNI 层方法; _Java_package_methodName _JNI_OnLoad _JNI_OnUnload
-exported_symbols_list 仅导出输入文件中列出的符号。其余的是隐藏的,因此我没有重复的符号。
我不知道为什么 Linux 和 Windows 上没有发生。