2015-10-29 5 views
1

Некоторые изменения в IBM J9 JVM 1.6 (более 1,5) приводят к ошибке связи, с которой мы столкнулись, чтобы вызвать исключение во время выполнения. В частности, мы используем JNI для загрузки разделяемой библиотеки, которая содержит объектные файлы с кодом:Связывание проблем с JNI при переходе с Java 1.5 на 1.6 под IBM J9

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); 
} 

Compile объектный файл без привязки

$ 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

0000000000201040 D _edata 
0000000000201048 B _end 
000000000000082d T _etext 
+1

Вы работаете на AIX? это выглядит знакомо? https://stackoverflow.com/questions/14023754/error-launching-c-executable-in-aix –

+0

Да, мы запускаем AIX 7, jdk 1.6 – Arthur

ответ

2

Основной программой (например,/USR/Java */JRE/бен/Java) должны экспортировать эти символы (ссылки вариант -Wl, -be : esyms.sym), а общий Lib должны импортировать их (связывая вариант -Wl, -BI: esyms.sym) содержание этого esyms.sym файла:

#! . 
_etext 
_edata 
_end 

Вы можете проверить, если ваш java экспортирует эти символы:

dump -Tv -X32_64 /usr/java*/jre/bin/java | grep _etext 
+0

Что делать, если ваша JRE не экспортирует эти символы? '$ dump -Tv -X32_64/usr/java6_64/jre/bin/java | grep _etext' ничего не возвращает. – ktbiz

+1

Ну, вы должны решить, хотите ли вы играть с управлением памятью java/libc (я не думаю, что вам нужно). Тем не менее, вы можете попробовать и повторно использовать java-исполняемый файл. –

+1

Что-то вроде этого: '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' –