有没有办法强制 Java VM 立即执行从 JNI 发送的异常?
Posted
技术标签:
【中文标题】有没有办法强制 Java VM 立即执行从 JNI 发送的异常?【英文标题】:Is there a way to force Java VM to execute immediately an exception sent from JNI? 【发布时间】:2019-11-01 11:05:03 【问题描述】:我需要从主 jni 线程发送一个 Java 异常。我使用以下代码来做这样的事情:
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 调用完成后才会引发异常。如果我们使用附加和分离,那么在分离调用中会引发异常。这是使事情更快的正确方法吗?我仍然不明白为什么将异常处理推迟到调用 DetachCurrentThread() 之前?我用安卓。非常感谢。
【问题讨论】:
【参考方案1】:当您在 JNI 代码中时,附加到当前线程的 Java 解释器没有运行。因此无法在 Java 端处理异常(展开堆栈帧、捕获等)。 Java 异常被创建为待处理,并且仅在 JNI 调用返回 Java 并且解释器继续执行当前 Java 线程时才真正抛出。
分离会伪造这个过程,但可能会使您的 JNI 代码处于不稳定状态:Java 正在运行,JNI 尚未返回并且仍在运行您的代码。
我首选的解决方案是像您一样抛出 Java 异常并立即抛出一个 C++ 异常,该异常仅(并且必须)在 JNI 边界处捕获并被丢弃。抛出 C++ 异常纯粹是为了导致堆栈展开和从 JNI 调用中快速干净退出。
【讨论】:
我的实验表明 JNI 在 detach 调用时停止运行。 Logcat 显示了 Java 和 C++ 的正确回溯,但在 Java 中无法捕获此异常。 :( @vollitwr AsDetachCurrentThread
返回结果 "..成功时返回 JNI_OK;失败时返回合适的 JNI 错误代码(负数)......"我看不出这会如何导致 JNI 线程退出。它将被记录为 "does not return" 或类似的。
我在分离之前和之后对 android 日志进行了写入。只有前者写。这意味着 JNI 在 detach 调用中停止。以上是关于有没有办法强制 Java VM 立即执行从 JNI 发送的异常?的主要内容,如果未能解决你的问题,请参考以下文章