【问题标题】:JNI native dll not returning jobjectArray crashes VMJNI 本机 dll 不返回 jobjectArray 导致 VM 崩溃
【发布时间】:2012-03-10 23:40:48
【问题描述】:

我正在开发一个调用本机 dll 库的 Java 应用程序。我调用的 c++ 方法的代码:

JNIEXPORT jobjectArray JNICALL Java_Surf_TopSurfWrapp_computeSurfExtractDescriptor__LSurf_TopSurfVisualword_2Ljava_lang_String_2(JNIEnv *env, jclass c, jobject vw, jstring imagePath)
{
c = env->GetObjectClass(vw);
printf("start\n");
jobjectArray ret = (jobjectArray) env->NewObjectArray(100, c, vw);

for (int i = 0; i < 100; i++)
{
    jmethodID visualWordConstructor = env->GetMethodID(c, "<init>", "(IFFIFFFF)V");
    jobject element = env->NewObject(c, visualWordConstructor, 1, 1.0, 1.0, 1, 1.0, 1.0, 1.0, 1.0);
    env->SetObjectArrayElement(ret, i, element);
}
    printf("end\n");
return ret;
}

我省略了一些计算,但问题似乎出在 JNI 返回 jobjectArray 时。 我的 Java 代码:

public class Wrapp {
    native public static TopSurfVisualword[] computeSurfExtractDescriptor(TopSurfVisualword initVW, String imagePath);
    static {
        System.loadLibrary("TopSurfWrapp");
    }

    public static void main(String[] args) {
    TopSurfVisualword[] d = TopSurfWrapp.computeSurfExtractDescriptor(new TopSurfVisualword(), "d:\\oil.jpg");
    }
}

我收到以下 JVM 错误:

debug:
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000076d73332, pid=3384, tid=1572
#
# JRE version: 7.0-b147
# Java VM: Java HotSpot(TM) 64-Bit Server VM (21.0-b17 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [ntdll.dll+0x53332]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# D:\Programming\Visual Studio projects\GPC\TopSurfWrapp\x64\Release\hs_err_pid3384.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
start
end
Java Result: 1

因为我收到“开始”和“结束”消息,所以我假设问题在于返回数组。 有问题的框架似乎位于 ntdll.dll (这不是我的动态库)。 请帮忙。

【问题讨论】:

  • 您的代码中没有错误检查。您将使用本机调试器附加到 java 进程并检查 dll 内部发生了什么。或者至少检查 env 方法调用的返回值并打印调试消息。
  • 返回值很好,在释放一些资源时出现了一些问题,这些资源用于计算创建作业的一些值。

标签: java c++ jvm java-native-interface


【解决方案1】:

我在我的系统上测试了您的示例,它运行良好。

一些调试提示...

1) 在本机代码中使用 printf 进行调试时,请在每个 printf 后面加上 fflush。

printf("debug message\n");
fflush(stdout);

2) 检查 JNI 函数的返回值是否为空。

jmethodID visualWordConstructor = env->GetMethodID(c, "<init>", "(IFFIFFFF)V"); 
if(visualWordConstructor==0) {
    // print/fflush an error message or throw an exception or both
    // stop processing and return to java now
}

3) 在 JNI 期间打印到标准输出和异常/错误可能很棘手。 尝试以下操作来观察行为。

jclass rx = env->FindClass("java/lang/RuntimeException");
printf("start\n");
fflush(stdout);

env->ThrowNew(rx, "thrown from native code");

printf("end\n");
fflush(stdout);

您将首先看到“结束”,然后看到异常。
这是意料之中的,因为 JNI 期间的异常是 排队,直到 java 端获得控制权。

【讨论】:

  • 感谢您的回答,您说得有道理,我已经弄清楚是什么导致了 EXCEPTION_ACCESS_VIOLATION 错误,这是释放一些资源的问题,这些资源用于计算创建作业。
猜你喜欢
  • 2015-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-23
  • 2010-11-22
  • 1970-01-01
相关资源
最近更新 更多