gpt4 book ai didi

从 JNI 运行时,Java ShutdownHook 无法加入主线程

转载 作者:塔克拉玛干 更新时间:2023-11-01 23:00:54 27 4
gpt4 key购买 nike

我有一些 Java 代码来创建一个关闭钩子(Hook),以便在客户端按下 ctrl+C 时干净地退出:

private static void shutdownHandler(Thread mainThread) {
try {
mainThread.join(30000);
} catch (InterruptedException e) {
}
}

public static void main(String[] args) {
final Thread mainThread = Thread.currentThread();
Thread shutdownThread = new Thread(() -> shutdownHandler(mainThread));
Runtime.getRuntime().addShutdownHook(shutdownThread);
}

当我从命令行运行它时,它按预期工作(主线程退出并几乎立即返回到命令提示符)。但是,如果我使用以下 C++ 代码编写一个调用它的 JNI 包装器:

JavaVMInitArgs vm_args;
// Populate vm_args

JavaVM *jvm;
JNIEnv *env;
JNI_CreateJavaVM(&jvm, reinterpret_cast<void**>(&env), &vm_args);

jclass mainClass = env->FindClass("path/to/my/class");
jmethod mainMethod = env->GetStaticMethodID(mainClass, "main", "([L" STRING_CLASS ";)V");

jclass stringClass = env->FindClass(STRING_CLASS);
jobjectArray mainArgs = env->NewObjectArray(0, stringClass, NULL);

env->CallStaticVoidMethod(mainClass, mainMethod, mainArgs);
jvm->DestroyJavaVM();

然后 shutdownHandler 方法挂起,直到 30 秒超时结束,然后将控制权返回给 C++ 代码并最终退出。有谁知道在从 JNI 调用启动时允许 shutdownHandler 方法加入主线程的方法吗?

最佳答案

在您的第一个示例中,主线程退出,然后 JVM 检测到没有剩余的非守护线程并将启动 JVM 关闭。此时,加入主线程没有问题,因为它甚至在关闭之前就已经结束了。

在你的第二个变体中,主线程,即通过 env -> CallStaticVoidMethod(…) 执行 main 方法的线程,正忙于执行 jvm -> 销毁 JavaVM()。由于该函数等待关闭处理程序完成,而您的关闭处理程序等待该线程完成,因此您遇到了死锁。

您也可以使用纯 Java 代码获得类似的行为。当您将 System.exit(0); 放在 main 方法的末尾时,让主线程启动关闭并等待其完成,您会遇到类似的死锁.

通常,您不应在关闭处理程序中执行join 操作。这些处理程序应该尽快清理并返回。

或者,作为 the documentation说:

Shutdown hooks run at a delicate time in the life cycle of a virtual machine and should therefore be coded defensively. They should, in particular, be written to be thread-safe and to avoid deadlocks insofar as possible. They should also not rely blindly upon services that may have registered their own shutdown hooks and therefore may themselves in the process of shutting down. Attempts to use other thread-based services such as the AWT event-dispatch thread, for example, may lead to deadlocks.

关于从 JNI 运行时,Java ShutdownHook 无法加入主线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52750512/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com