为什么正式的JVM文档与在addShutdownHook中的实现相矛盾? [英] Why does the official JVM documentation contradict its implementation in addShutdownHook?

查看:178
本文介绍了为什么正式的JVM文档与在addShutdownHook中的实现相矛盾?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

类别为Thread的关闭挂钩是否在调用关闭的线程上运行它们的可运行代码,还是自己运行.

There's a bit of a clash for whether shutdown hooks, which are of class Thread, run their runnable code on the thread on which the shutdown was called, or run on themselves.

addShutdownHookThread作为参数.这意味着线程将自行启动并运行其run方法.这也与

addShutdownHook takes a Thread as a parameter. This implies the thread will start and run its run method on itself. This is also consistent with the documentation for addShutdownHook:

public void addShutdownHook(线程钩子)

public void addShutdownHook(Thread hook)

注册一个新的虚拟机关闭挂钩. Java虚拟机将响应以下两种事件而关闭:

Registers a new virtual-machine shutdown hook. The Java virtual machine shuts down in response to two kinds of events:

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

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

A shutdown hook is simply an initialized but unstarted thread. When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled. Finally, the virtual machine will halt. Note that daemon threads will continue to run during the shutdown sequence, as will non-daemon threads if shutdown was initiated by invoking the exit method.

(强调我的)

但是,代码为(!!我的评论)

请注意,这是

Note this is little changed from JDK 6, which makes the problem all the clearer:

/* 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在该线程上运行是自然而正确的.)

At first I thought I was reading this wrong and calling run magically started the thread. But it doesn't. I wrote the run code myself. That code does not start a thread (in the case of a Thread, it's natural and correct to assume run runs on the thread.)

所以这里有些真的错.是Javadoc和addShutdownHook方法的签名,根据代码,不是应该每个代码都使用一个线程,而是一个可运行的线程?是实施吗?还是更可能的罪魁祸首-我?如果可以,怎么办?

So something is really wrong here. Is it the Javadoc and the signature of the addShutdownHook method, which per the code should not be taking a thread, but a runnable? Is it the implementation? Or is it the more likely culprit - me; and if so, how?

推荐答案

您正在混淆Shutdown.runHooks()ApplicationShutdownHooks.runHooks().您在Runtime中注册的关闭挂钩在ApplicationShutdownHooks中注册,而ApplicationShutdownHooks本身将Runnable注册为Shutdown挂钩

You are confusing Shutdown.runHooks() and ApplicationShutdownHooks.runHooks(). The shutdown hooks you register with Runtime are registered with ApplicationShutdownHooks, which itself registers a Runnable as a Shutdown hook

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#addShutdownHook(Thread)的(oracle jdk7)代码.

For reference, the (oracle jdk7) code for Runtime#addShutdownHook(Thread).

public void addShutdownHook(Thread hook) {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new RuntimePermission("shutdownHooks"));
    }
    ApplicationShutdownHooks.add(hook);
}

这篇关于为什么正式的JVM文档与在addShutdownHook中的实现相矛盾?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆