在 IBM J9 下从 Java 1.5 升级到 1.6 时 JNI 的链接问题
Posted
技术标签:
【中文标题】在 IBM J9 下从 Java 1.5 升级到 1.6 时 JNI 的链接问题【英文标题】:Linking problems with JNI when going from Java 1.5 to 1.6 under IBM J9 【发布时间】:2016-01-30 07:56:33 【问题描述】:IBM J9 JVM 1.6(超过 1.5)中的一些更改导致我们遇到的链接错误导致运行时异常。具体来说,我们使用 JNI 来加载包含目标文件的共享库和代码:
extern _edata;
extern _etext;
extern _end;
这些是内存子系统中使用的地址,应该由链接器提供。但是,当我们编译共享库时,AIX 链接器不会链接它们(但是,如果您制作可执行文件,它会正确链接)。
JNI 错误信息:
java.lang.UnsatisfiedLinkError: oas-jni (rtld: 0712-001 Symbol _edata was referenced
from module /usr/IBM/blackbird/lib/liboas-jni.so(), but a runtime definition of the symbol was not found.
rtld: 0712-001 Symbol _etext was referenced from module /usr/IBM/blackbird/lib/liboas-jni.so(), but a runtime definition of the symbol was not found.
rtld: 0712-001 Symbol _end was referenced from module /usr/IBM/blackbird/lib/liboas-jni.so(), but a runtime definition of the symbol was not found.
rtld: 0712-002 fatal error: ex)
at java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:1035)
at java.lang.ClassLoader.loadLibraryWithClassLoader(ClassLoader.java:999)
at java.lang.System.loadLibrary(System.java:507)
at com.integrasolv.owl.oas.OAS_Init.<clinit>(OAS_Init.java:16)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:201)
at com.integrasolv.owl.oas.OAS_Agent.<clinit>(OAS_Agent.java:87)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:201)
at blackbird.testclient.TestClient.initOwlProcesses(TestClient.java:120)
at blackbird.testclient.TestClient.main(TestClient.java:75)
Exception in thread "main" java.lang.UnsatisfiedLinkError: com/integrasolv/owl/oas/OAS_Agent.setEnv(Ljava/lang/String;Ljava/lang/String;)V
at blackbird.testclient.TestClient.initOwlProcesses(TestClient.java:120)
at blackbird.testclient.TestClient.main(TestClient.java:75)
Bare Bones 测试文件:
// test.c
#include <stdio.h>
#include <stdlib.h>
extern char _etext, _edata, _end;
int runtest()
printf("First address past:\n");
printf(" program text (etext) %10p\n", &_etext);
printf(" initialized data (edata) %10p\n", &_edata);
printf(" uninitialized data (end) %10p\n", &_end);
exit(EXIT_SUCCESS);
编译目标文件而不链接
$ gcc -c test.c
从 test.o 创建一个共享库
$ gcc -shared -Wl,-G -o libtest.a test.c
请注意,-G 包括链接器的 -berok 选项,忽略错误。否则我们会在此处看到 _etext、_edata 和 _end 的一些未定义符号错误。
从共享库中转储符号表
$ dump -Tv libtest.a
libtest.a:
***Loader Section***
***Loader Symbol Table Information***
[Index] Value Scn IMEX Sclass Type IMPid Name
[0] 0x200006e4 .data RW SECdef [noIMid] __rtinit
[1] 0x00000000 undef IMP DS EXTref libgcc_s.a(shr.o) __cxa_finalize
[2] 0x00000000 undef IMP DS EXTref libc.a(shr.o) exit
[3] 0x00000000 undef IMP DS EXTref libc.a(shr.o) printf
[4] 0x00000000 undef IMP DS EXTref libc.a(shr.o) strtod
[5] 0x00000000 undef IMP DS EXTref libc.a(shr.o) __fd_select
[6] 0x00000000 undef IMP DS EXTref libc.a(shr.o) puts
[7] 0x00000000 undef IMP DS EXTref libc.a(shr.o) __strtollmax
[8] 0x200006d0 .data EXP RW Ldef [noIMid] __dso_handle
[9] 0x20000750 .data EXP DS Ldef [noIMid] __init_aix_libgcc_cxa_atexit
[10] 0x20000780 .data EXP DS Ldef [noIMid] runtest
[11] 0x00000000 undef IMP PR EXTref .. _etext
[12] 0x00000000 undef IMP PR EXTref .. _edata
[13] 0x00000000 undef IMP PR EXTref .. _end
纳米输出:
$ nm libtest.a|grep _e
_edata U -
_edata d 536872908 4
_end U -
_end d 536872916 4
_etext U -
_etext d 536872900 4
我并不完全清楚这里发生了什么。在 linux 上,这工作正常。在 GNU/Linux 上的同一测试中输出 nm 命令
0000000000201040 D _edata
0000000000201048 B _end
000000000000082d T _etext
【问题讨论】:
您在 AIX 上运行吗?这看起来很熟悉吗? ***.com/questions/14023754/… 是的,我们正在运行 AIX 7,jdk 1.6 【参考方案1】:主程序(例如/usr/java*/jre/bin/java)应该导出这些符号(链接选项-Wl,-bE:esyms.sym),共享库应该导入它们(链接选项 -Wl,-bI:esyms.sym) 这个 esyms.sym 文件的内容:
#! .
_etext
_edata
_end
您可以检查您的 java 是否导出了这些符号:
dump -Tv -X32_64 /usr/java*/jre/bin/java | grep _etext
【讨论】:
如果您的 JRE 不导出这些符号怎么办?$ dump -Tv -X32_64 /usr/java6_64/jre/bin/java | grep _etext
不返回任何内容。
好吧,你应该决定你是否真的想使用 java/libc 的内存管理(我认为你不应该这样做)。尽管如此,您可以尝试重新链接 java 可执行文件。
类似这样的东西:ld -b64 -bE:esyms.sym -o java_haxored /usr/lib/crt0_64.o /usr/java6_64/jre/bin/java /usr/lib/libiconv.a /usr/lib/libpthread.a /usr/lib/libc.a
以上是关于在 IBM J9 下从 Java 1.5 升级到 1.6 时 JNI 的链接问题的主要内容,如果未能解决你的问题,请参考以下文章