带有JNI调用的SIGSEGV将jlong​​转换为long

时间:2017-07-25 13:23:59

标签: java c linux segmentation-fault java-native-interface

我正在与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的强制转换可能会导致这种错误

非常感谢你的帮助。

0 个答案:

没有答案