我正在与JNI合作,从我的Java应用程序调用软件编辑器提供的外部C库,以便从他们的应用程序访问/写入数据。
我通过一些电话收到SIGSEGV致命错误,但我无法找到原因。 这里是JVM给出的错误日志:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f1b357729e0, pid=18693, tid=139752817592064
#
# JRE version: 6.0_45-b06
# Java VM: Java HotSpot(TM) 64-Bit Server VM (20.45-b01 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C 0x00007f1b357729e0
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
--------------- T H R E A D ---------------
Current thread (0x00007f1b1001d000): JavaThread "http-bio-10.70.4.12-10767-exec-12" daemon [_thread_in_native, id=18888, stack(0x00007f1abcfc8000,0x00007f1abd0c9000)]
siginfo:si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x00007f1b357729e0
Registers:
RAX=0x00007f1b35dfd990, RBX=0x000000000000000b, RCX=0x000000000000000b, RDX=0x00007f1ac1d3d650
RSP=0x00007f1abd0c5178, RBP=0x00007f1abd0c51a0, RSI=0x000000000000000b, RDI=0x00007f1ac1d3d650
R8 =0x00007f1b506c9278, R9 =0x00007f1b1001e328, R10=0x00007f1b45011894, R11=0x00007f1b503b2d10
R12=0x00007f1ac1d3d650, R13=0x00000000e2de9358, R14=0x00007f1abd0c5260, R15=0x00007f1b1001d000
RIP=0x00007f1b357729e0, EFLAGS=0x0000000000010202, CSGSFS=0x0000000000000033, ERR=0x0000000000000014
TRAPNO=0x000000000000000e
Top of Stack: (sp=0x00007f1abd0c5178)
0x00007f1abd0c5178: 00007f1b35beed30 00007f1b1001d000
...
0x00007f1abd0c5358: 00007f1abd0c5358 00000000e321a20a
0x00007f1abd0c5368: 00007f1abd0c5440 00000000e4699898
Instructions: (pc=0x00007f1b357729e0)
0x00007f1b357729c0:
[error occurred during error reporting (printing registers, top of stack, instructions near pc), id 0xb]
Register to memory mapping:
RAX=0x00007f1b35dfd990: s_fnAmGetFieldLongValue+0 in /app/rct/ASK4IT/2/tomcat7/installedApps/ask4itWeb.war/WEB-INF/dll/HP/AssetManager/x64/libamapijni.so at 0x00007f1b35be5000
RBX=0x000000000000000b is an unknown value
RCX=0x000000000000000b is an unknown value
RDX=0x00007f1ac1d3d650 is an unknown value
RSP=0x00007f1abd0c5178 is pointing into the stack for thread: 0x00007f1b1001d000
RBP=0x00007f1abd0c51a0 is pointing into the stack for thread: 0x00007f1b1001d000
RSI=0x000000000000000b is an unknown value
RDI=0x00007f1ac1d3d650 is an unknown value
R8 =0x00007f1b506c9278: <offset 0xaa2278> in /tech/java/oracle/jdk-1.6.0_45/jre/lib/amd64/server/libjvm.so at 0x00007f1b4fc27000
R9 =0x00007f1b1001e328 is an unknown value
R10=0x00007f1b45011894 is an Interpreter codelet
method entry point (kind = native_synchronized) [0x00007f1b450114c0, 0x00007f1b45011e80] 2496 bytes
R11=0x00007f1b503b2d10: <offset 0x78bd10> in /tech/java/oracle/jdk-1.6.0_45/jre/lib/amd64/server/libjvm.so at 0x00007f1b4fc27000
R12=0x00007f1ac1d3d650 is an unknown value
R13=0x00000000e2de9358 is an oop
{method}
- klass: {other class}
R14=0x00007f1abd0c5260 is pointing into the stack for thread: 0x00007f1b1001d000
R15=0x00007f1b1001d000 is a thread
Stack: [0x00007f1abcfc8000,0x00007f1abd0c9000], sp=0x00007f1abd0c5178, free space=1012k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C 0x00007f1b357729e0
j com.afkl.ask4it.amapi.JNI.Base.AmGetFieldLongValue(JJ)J+0
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j com.afkl.ask4it.amapi.JNI.Base.AmGetFieldLongValue(JJ)J+0
J com.afklm.askfourit.query.QueryUtil.getFieldValue(JJJLjava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
j com.afklm.askfourit.dao.Ask4ItModelDAO.createAsk4itModelBean(JJ)Lcom/afklm/askfourit/entity/Ask4ItModel;+602
...
正如您在堆栈中看到的,导致崩溃的方法就是这样:
JNIEXPORT jlong JNICALL Java_com_afkl_ask4it_amapi_JNI_Base_AmGetFieldLongValue(JNIEnv * env, jclass c, jlong jlhQuery, jlong jiPos)
{
long lFieldVal = AmGetFieldLongValue(jl2c(jlhQuery), jl2c(jiPos));
if(fhLog)
amapi_JNI_log("AmGetFieldLongValue","object %ld pos %ld : %ld",jl2c(jlhQuery), jl2c(jiPos),lFieldVal);
return lFieldVal;
}
此函数只调用外部库的本机函数AmGetFieldLongValue。它只是一个允许Java调用它的转换,除了传递参数和检索结果之外什么都不做。
我能想到的唯一导致SIGSEGV的是调用jl2c将jlong转换为long,定义为:
#define jl2c(_jl) ((long)(_jl))
或者返回值lFieldVal在此函数中定义为long,而该方法返回jlong。
我希望那些转换造成麻烦,因为我读到某个地方&#34;传递char *需要jstring可能会导致JVM崩溃&#34;。 之前我有很多JVM崩溃,但我重写了这个JNI以停止这样做,并传递使用jstring的jbyteArray,然后使用此代码将其转换为char *:
jsize lengthTable = (*env)->GetArrayLength(env, jstrTable);
jbyte* jByteStrTable = (*env)->GetByteArrayElements(env, jstrTable, 0);
char* pszTable = malloc(lengthTable + 1);
memcpy(pszTable, jByteStrTable, lengthTable);
pszTable[lengthTable] = '\0';
现在我似乎没有更多崩溃这个函数,所以我希望这段代码能够纠正我以前的问题,但现在看来我和其他类型的转换有同样的问题。
但我无法找出它的错误。 我读了一个jlong是一个64位有符号整数,如果将long定义为32位整数但是我不知道如何安全演员或者别的东西,从jlong到long的强制转换可能会导致这种错误
非常感谢你的帮助。