JNI 未捕获的类型异常<unknown>...这是怎么发生的?



我有一些Java代码调用c++代码,而c++代码反过来调用Java,全部通过JNI。我们得到了臭名昭著的"hs_err_pidXXXX.log",奇怪的是,当我们在当前挂起的异常上调用JNIEnv_::GetMethodID(myJniEnv->GetObjectClass(anException), "printStackTrace", "()V")时,它就发生了!所以我们添加了:

if ((javaException = getJniEnv()->ExceptionOccurred()) != NULL)
{
   jniEnv->ExceptionDescribe();
   .... <other exception handling code> ...
}

…每次调用JNI后,我们都试图发现发生了什么异常。ExceptionDescribe()的结果是:

Uncaught exception of type <unknown>

这是怎么发生的?上面的anException值直接来自于对anException = myJniEnv->ExceptionOccurred()的JNI调用,它应该产生一个throwable,对吗?我认为,我应该能够在抛出对象上打印堆栈跟踪,而不会导致JNI崩溃。有人见过这样的东西吗?

这听起来像是内存损坏问题,可能是因为Java本地引用已经被清理了。尝试在Java命令行中添加以下一些或全部选项(或C/c++中的JVM创建参数):

  -verbose:jni
  -verbose:gc
  -Xcheck:jni
其中最有趣的可能是-Xcheck:jni(参见命令行文档)。这将增加一堆检查,比如使用已经删除的本地引用,并在检测到错误时抛出异常,而不是在内存已经损坏时在程序的更深处抛出异常。一旦在错误的原始来源处获得java异常,使用调试器(如查找c++崩溃位置的gdb)或java堆栈跟踪来准确地找到错误发生的位置,并有希望查明导致问题的确切对象,应该会容易得多。

我从我们的常驻JNI战士那里学来的;)

相关内容

最新更新