有没有办法强制 Java VM 立即执行从 JNI 发送的异常?

Is there a way to force Java VM to execute immediately an exception sent from JNI?

我需要在 Java 中从主 jni 线程发送异常。我使用下面的代码来做这样的事情:

if (vm->AttachCurrentThread(reinterpret_cast<void **>(&env), nullptr) != JNI_OK || env == nullptr) {
    std::cerr << "Get env for current thread failed.\n";
    return ;
}
jclass exClass = env->FindClass("[JavaClassName]");
if (exClass != nullptr) {
    env->ThrowNew(exClass, "[ExceptionMessage]");
}
env->DeleteLocalRef(exClass);
vm->DetachCurrentThread();

它以某种方式工作。我发现,如果我们不使用附加和分离(只使用抛出),那么只有在 Java VM 的 jni 调用完成后才会引发异常。如果我们使用 attach 和 detach,那么在 detach 调用中会引发异常。这是让事情变得更快的正确方法吗?我仍然不明白为什么异常处理被推迟到调用 DetachCurrentThread() 时?我使用 Android。非常感谢。

当您在 JNI 代码中时,附加到您当前线程的 Java 解释器不是 运行。因此无法处理 Java 端的异常(展开堆栈帧、捕获等)。 Java 异常被创建为挂起,只有当 JNI 调用 returns 到 Java 并且解释器的执行继续为您当前的 Java 线程时才会真正抛出。

在这个过程中分离假货,但可能会使您的 JNI 代码处于不稳定状态:Java 现在是 运行,JNI 尚未返回并且仍然是 运行 您的代码。

我的首选解决方案是像您一样抛出 Java 异常并立即抛出仅(并且必须)在 JNI 边界捕获并丢弃的 C++ 异常。抛出 C++ 异常纯粹是为了导致堆栈展开并从 JNI 调用中快速干净地退出。