当前位置: 首页 > 知识库问答 >
问题:

为什么官方JVM文档与addShutdownHook中的实现相矛盾?

龚跃
2023-03-14

对于类为Thread的shutdown钩子是在调用shutdown的线程上运行其可运行代码,还是在其自身上运行,存在一些冲突。

addShutdown HookThread作为参数。这意味着线程将启动并在自己身上运行其run方法。这也与addShutdown Hook的留档一致:

公共void addShutdownHook(线程挂钩)

注册新的虚拟机关闭挂钩。Java虚拟机关闭以响应两种事件:

  • 当最后一个非守护进程线程退出或调用exit(相当于System.exit)方法时,程序正常退出,或
  • 响应用户中断(如键入^C)或系统范围内的事件(如用户注销或系统关闭),终止虚拟机

关闭钩子只是一个初始化但未启动的线程。当虚拟机开始其关闭序列时,它将以某种未指定的顺序启动所有注册的关闭挂钩,并让它们同时运行。当所有钩子完成后,如果启用了退出时的终结,那么它将运行所有未调用的终结器。最后,虚拟机将停止。注意,守护进程线程将在关闭序列期间继续运行,如果通过调用exit方法启动关闭,则非守护进程线程也将继续运行。

(强调矿山)

但是,代码如下:

/* Run all registered shutdown hooks
 */
private static void runHooks() {
    for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
        try {
            Runnable hook;
            synchronized (lock) {
                // acquire the lock to make sure the hook registered during
                // shutdown is visible here.
                currentRunningHook = i;
                hook = hooks[i];
            }
            if (hook != null) hook.run();  // not Thread.start - Runnable.run (!!)
        } catch(Throwable t) {
            if (t instanceof ThreadDeath) {
                ThreadDeath td = (ThreadDeath)t;
                throw td;
            }
        }
    }
}

!!评论我的)

注意,这与JDK 6相比变化不大,这使问题更加清楚:

/* Run all registered shutdown hooks
 */
private static void runHooks() {
    /* We needn't bother acquiring the lock just to read the hooks field,
     * since the hooks can't be modified once shutdown is in progress
     */
    for (Runnable hook : hooks) {
        try {
            hook.run();
        } catch(Throwable t) {
            if (t instanceof ThreadDeath) {
                ThreadDeath td = (ThreadDeath)t;
                throw td;
            }
        }
    }
}

起初我以为我读错了,调用run神奇地启动了线程。但事实并非如此。我自己编写了run代码。该代码不会启动线程(在Thread的情况下,假设run在线程上运行是自然和正确的。)

所以这里确实出了点问题。它是Javadoc和addShutdownHook方法的签名吗?每个代码都不应该采用线程,而是可运行的?这是实施吗?还是更可能的罪魁祸首——我;如果是这样,怎么做?

共有1个答案

左恺
2023-03-14

您混淆了Shutdown.runHooks()Application Shutdown Hooks.runHooks()。您在Runtime中注册的关闭挂钩在Application ationShutdown Hooks中注册,它本身将Runnable注册为Shutdown挂钩

static {
    try {
        Shutdown.add(1 /* shutdown hook invocation order */,
            false /* not registered if shutdown in progress */,
            new Runnable() {
                public void run() {
                    runHooks(); // (!!)  your hooks
                }
            }
        );
        hooks = new IdentityHashMap<>();
    } catch (IllegalStateException e) {
        // application shutdown hooks cannot be added if
        // shutdown is in progress.
        hooks = null;
    }
}

同时运行关闭挂钩

static void runHooks() { // In ApplicationShutdownHooks
    Collection<Thread> threads;
    synchronized(ApplicationShutdownHooks.class) {
        threads = hooks.keySet();
        hooks = null;
    }

    for (Thread hook : threads) { // (!!) your hooks
        hook.start();
    }
    for (Thread hook : threads) {
        try {
            hook.join();
        } catch (InterruptedException x) { }
    }
}

作为参考,Runtime#addShutdown Hook(Thread)的(oracle jdk7)代码。

public void addShutdownHook(Thread hook) {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new RuntimePermission("shutdownHooks"));
    }
    ApplicationShutdownHooks.add(hook);
}
 类似资料:
  • 译者注: 原英文文档地址为 https://linkerd.io/docs/ 欢迎来到 linkerd! 本文档将帮助您开始使用。 它分为几个主要部分: 概述:以 high-level 的方式介绍 linkerd 的特性,解释其背后的理由,并介绍文档其余内容中使用的重要概念。 开始:提供在各种环境中设置和运行 linkerd 的具体说明。从这里开始快速入门。 特性:涵盖 linkerd 的主要功能

  • 译注 原英文文档地址为 https://istio.io/docs/ 正文 欢迎来到Istio。 欢迎来到Istio的最新文档主页。从这里您可以通过以下链接了解有关Istio的所有信息: 概念 概念解释了Istio的一些关键点。在这里您可以了解Istio的工作原理及其实现。 安装 在不同的环境下(如Kubernetes、Consul等)安装Istio控制平面,以及在应用程序部署中安装sidecar

  • 欢迎来到 Sublime Text 编辑器的非官方文档。Sublime Text 是一个可以运行在 OS X、Windows 和 Linux 上的多功能编辑器,你可以用它来写代码或是写散文。

  • Three.js 是一款运行在浏览器中的 3D 引擎,你可以用它创建各种三维场景,包括了摄影机、光影、材质等各种对象。你可以在它的主页上看到许多精采的演示。 在线示例:https://www.wenjiangs.com/wp-content/uploads/three.js/examples/ 在线编辑器:https://www.wenjiangs.com/wp-content/uploads/t

  • Flarum 是一款非常简洁的开源论坛软件。它响应快速、简便易用,拥有打造一片成功的社区所需的所有功能。本用户指南将帮助您使用 Flarum 搭建自己的论坛,并教授您管理社区的基础知识。

  • Electron 可以让你使用纯 JavaScript 调用丰富的原生 APIs 来创造桌面应用。你可以把它看作是专注于桌面应用而不是 web 服务器的,io.js 的一个变体。