集合没有在java关闭钩子中迭代

时间:2015-10-02 16:22:39

标签: java shutdown-hook

我已经在这个荒谬的问题上奋斗了几个小时,所以现在我正在寻求帮助。

1班轮:我的关机钩子在完成任务之前显然已经终止了。

我正在运行的代码如下所示:

class Test {

    static {
        Runtime.getRuntime().addShutdownHook(new Thread(Test::shutdown));
    }

    // more methods
    private static void shutdown() {
        Collection<Foo> coll = some.instance.ofHashMap.values();
        System.out.println("collSize=" + coll.size());
        for (Foo o : coll) {
            System.out.println("Calling bar on foo");
            o.bar();
        }
        System.out.println("End of hook");
    }
}

但输出是:

collSize=1

如果我使用-server选项运行jvm,我可能会很幸运,并且foo&#34;&#34;呼叫吧打印,但它仍然没有打印&#34;挂钩结束&#34;。

不幸的是,我还没有能够创建一个显示问题的简短可执行示例。我有一个,但它显示一切正常工作,并按预期迭代集合。 上面的代码是我正在处理的一个更大的程序的摘录,但是我的关闭是钩子只是做了上面的事情(得到一个非空的集合并迭代)。

有关可能发生的事情的任何想法?我完全迷失在这里......

注意:   - 使用Java 8u45编写,编译和运行代码   - 我用Ctrl + C终止程序,因此,JVM存在代码130

2 个答案:

答案 0 :(得分:1)

the docs(强调我的)你只承诺&#34;尽力而为&#34; for shutdown hooks:

  

关闭挂钩在虚拟机的生命周期中的微妙时间运行,因此应该进行防御性编码。特别是它们应该被编写为线程安全的并且尽可能避免死锁。他们也不应盲目依赖可能已经注册了自己的关机钩子的服务,因此他们自己可能正在关闭。例如,尝试使用其他基于线程的服务(例如AWT事件派发线程)可能会导致死锁。

     

关机挂钩也应该快速完成工作。当程序调用exit时,期望虚拟机将立即关闭并退出。当虚拟机因用户注销或系统关闭而终止时,基础操作系统可能只允许一段固定的时间来关闭和退出。因此,不建议尝试任何用户交互或在关闭钩子中执行长时间运行的计算。

所以,基本上如果还有其他地方可以做到,那就去做吧。如果你必须在关机钩子中这样做,那就快点。

答案 1 :(得分:0)

原来:

  • 主要是 IO问题:与上面的示例不同,我使用log4j2中的记录器来打印信息。 log4j2有自己的shutdownHook,它比我的关闭钩子更快地杀死所有记录器,因为在JVM中并行执行shutdown钩子。在disabling log4j2 shutdownHook之后,一切似乎都按预期工作。
  • 钩子总是完全执行(通过将调试器附加到jvm很容易证明)
  • 在我的特殊情况下,我忘了关机+等待我的线程池来做我想要的所有清理工作
  • 我应该在发布之前睡觉:/

感谢大家的快速回复和帮助。