希望你今天过得愉快。
我有一个JNI so库,其中包含以下代码。
static JavaVM * s_vm = NULL; // The VM pointer
// The following exported method is called by JVM when this so is loaded
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
s_vm = vm;
return JNI_VERSION_1_6;
}
// And a native thread is created to fire Java method
apr_thread_t * thread;
apr_threadattr_t * attr;
apr_threadattr_create( &attr, pool);
apr_threadattr_detach_set( attr, 1);
apr_threadattr_stacksize_set( attr, 1024 * 1024 * 10);
apr_thread_create( &thread, attr, receive_thread, pool, pool);
// within the created thread, the following method is called somehow
void onMsgReceived(const char * replyChannel, const unsigned char * ctrl, uint32_t ctrlLen, const unsigned char * payload, uint32_t payloadLen)
{
JNIEnv * env = NULL;
int env_stat = s_vm->GetEnv((void **)&env, JNI_VERSION_1_6);
if (env_stat == JNI_EDETACHED) {
if (s_vm->AttachCurrentThread((void **) &env, NULL) != 0) { // <-- this line crashes
return;
}
} else if (env_stat == JNI_OK) {
} else if (env_stat == JNI_EVERSION) {
return;
}
if (env_stat == JNI_EDETACHED)
s_vm->DetachCurrentThread();
}
我将一个调试器附加到进程,它是AttachCurrentThread
在JVM中导致SEGFAULT。调用JNI_OnLoad
时,s_vm的值相同。
奇怪的是,相同的代码在Windows上运行,但在CentOS6.5上运行失败 我也尝试了与Windows上相同的JRE版本,但问题仍然存在。
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
我不确定这是否是由多个GLIBC版本引起的?
$objdump -p ./libinterop_d.so
./libinterop_d.so: file format elf64-x86-64
Program Header:
LOAD off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
filesz 0x0000000000071b70 memsz 0x0000000000071b70 flags r-x
LOAD off 0x0000000000072000 vaddr 0x0000000000272000 paddr 0x0000000000272000 align 2**21
filesz 0x0000000000003358 memsz 0x0000000000015be8 flags rw-
DYNAMIC off 0x0000000000073a70 vaddr 0x0000000000273a70 paddr 0x0000000000273a70 align 2**3
filesz 0x00000000000001c0 memsz 0x00000000000001c0 flags rw-
NOTE off 0x00000000000001c8 vaddr 0x00000000000001c8 paddr 0x00000000000001c8 align 2**2
filesz 0x0000000000000024 memsz 0x0000000000000024 flags r--
TLS off 0x0000000000072000 vaddr 0x0000000000272000 paddr 0x0000000000272000 align 2**3
filesz 0x0000000000000000 memsz 0x0000000000000010 flags r--
EH_FRAME off 0x0000000000065814 vaddr 0x0000000000065814 paddr 0x0000000000065814 align 2**2
filesz 0x000000000000201c memsz 0x000000000000201c flags r--
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**3
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
Dynamic Section:
NEEDED librt.so.1
NEEDED libm.so.6
NEEDED libpthread.so.0
NEEDED libc.so.6
NEEDED ld-linux-x86-64.so.2
INIT 0x000000000001eb40
FINI 0x000000000005c4e8
GNU_HASH 0x00000000000001f0
STRTAB 0x0000000000009900
SYMTAB 0x00000000000026a0
STRSZ 0x000000000000d351
SYMENT 0x0000000000000018
PLTGOT 0x0000000000273fd8
PLTRELSZ 0x00000000000037c8
PLTREL 0x0000000000000007
JMPREL 0x000000000001b378
RELA 0x00000000000176d0
RELASZ 0x0000000000003ca8
RELAENT 0x0000000000000018
VERNEED 0x00000000000175e0
VERNEEDNUM 0x0000000000000005
VERSYM 0x0000000000016c52
RELACOUNT 0x00000000000000ee
Version References:
required from librt.so.1:
0x09691a75 0x00 10 GLIBC_2.2.5
required from libm.so.6:
0x09691a75 0x00 09 GLIBC_2.2.5
required from ld-linux-x86-64.so.2:
0x0d696913 0x00 06 GLIBC_2.3
required from libc.so.6:
0x0d696919 0x00 11 GLIBC_2.9
0x09691973 0x00 08 GLIBC_2.3.3
0x0d696914 0x00 07 GLIBC_2.4
0x0d696913 0x00 05 GLIBC_2.3
0x09691a75 0x00 04 GLIBC_2.2.5
required from libpthread.so.0:
0x09691a75 0x00 03 GLIBC_2.2.5
0x0d696914 0x00 02 GLIBC_2.4
更新:我发现如果从项目中移除lanterna,一切正常。但是如果我将lanterna jar添加到项目中,即使没有代码可以调用它,也会发生这种情况。
lanterna与JNI不相容?
答案 0 :(得分:0)
最后,我避免使用从pthread或apr创建的线程来绕过这个问题。并使用Java线程调用方法并阻塞,直到有东西要返回。