JVM终止后会发生什么? [英] What happens when the JVM is terminated?

查看:135
本文介绍了JVM终止后会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在互联网上四处寻找这个问题的答案,但我必须得出结论:我必须要么在网上找东西要么很糟糕,要么我在找错了地方。

I looked around a lot on the internet to find an answer to this question, but I had to conclude I must be either terrible at finding things on the internet or I am looking in the wrong places.

现在我希望有人可以帮助我解决我的问题:

Now I hope someone here could help me with my question:

当JVM终止时会发生什么 System.exit(0) ^ C 或者其他类似的东西?我到处读到诸如流程刚被吹走和每个线程都停止之类的事情,但我想知道究竟发生了什么。我已经知道 shutdownHook 以某种方式仍然被执行,但之前发生了什么,并且在所有这些线程完成之后还有什么东西吗?

What happens when the JVM is terminated with System.exit(0) or ^C or anything of that kind? I read everywhere things like "the process is just blown away" and "every single thread is stopped", but I would like to know what happens exactly. I already know there is the shutdownHook that somehow still gets executed, but what has happened before and is there anything after all these threads have finished?

我的问题的真正原因是因为我想正确地实现这样的 shutdownHook 并对可能仍然执行的内容做出正确的假设没有。

The real reason for my question is because I would like to implement such a shutdownHook correctly and make the right assumptions about what might still be executed and what not.

一些代码:

class SomeObject {

    private boolean stopped;

    SomeObject() {
        stopped = false;
        Thread hook = new Thread() {

            @Override
            public void run() {
                stopped = true;
            }

        };
        hook.setPriority(Thread.MAX_PRIORITY);
        Runtime.getRuntime().addShutdownHook(hook);
    }

    boolean map(Iterator<Object> it) {
        while(it.hasNext() && !stopped) {
            writeToOtherObject(it.next());
            it.remove();
        }
        //have calculations finished?
        return !it.hasNext();
    }
}

地图 function计算在其他对象中收集的结果。在所有内容都被分解之前,该对象应存储在某个文件中(通过普通优先级 shutdownHook s)。这里的 shutdownHook 是否有意义?至于我现在所理解的,我假设所有线程都被首先销毁,然后才运行 shutdownHook (同时,但我假设首先运行高优先级线程。 ..)然后对象最终确定。这使得上面的代码相当无用,因为这个 shutdownHook 的意图恰恰是确保在关闭已经开始时没有启动新的循环。我理解得好,还是忘记了什么?

The map function computes results that are gathered in some other object. This object should be stored in some file before everything is broken down (by normal-priority shutdownHooks too). Does the shutdownHook here make sense? For as far I understood it now, I assume all threads are destroyed first and only then the shutdownHooks are run (concurrently, but I assume high-priority threads are run first...) and then objects are finalized. This makes the code above rather useless, because the intention of this shutdownHook would exactly be to make sure no new loop is started when the shutdown has already started. Did I understand it well, or did I forget something?

推荐答案

让我们从可以启动关机序列的不同方式开始:

Let's begin from the different ways the shutdown sequence can be initiated:


  • 最后一个非守护程序线程结束。

  • JVM被中断(使用 ctrl C 或发送SIGINT)。

  • JVM终止(通过发送SIGTERM)

  • 其中一个线程调用 System.exit() Runtime.exit()

  • The last non-daemon thread ends.
  • The JVM is interrupted (by using ctrlC or sending SIGINT).
  • The JVM is terminated (by sending SIGTERM)
  • One of the threads calls System.exit() or Runtime.exit().

当调用 System.exit(int)时,它调用 Runtime.exit ()。它检查安全管理器是否允许以给定状态退出,如果是,则调用 Shutdown.exit()

When System.exit(int) is called, it calls Runtime.exit(). It checks with the security manager whether it is permitted to exit with the given status, and if so, calls Shutdown.exit().

如果你打断了JVM或系统发送了TERM信号,那么默认情况下,直接调用 Shutdown.exit()而不检查安全性经理。

If you interrupted the JVM or the system sent it the TERM signal, then by default, Shutdown.exit() is called directly without checking with the security manager.

Shutdown 类是 java中的内部包私有类。郎。除其他外,它有一个 exit()和一个 halt()方法。它的 exit()方法会做一些事情来防止钩子被执行两次,依此类推,但基本上,它的作用是

The Shutdown class is an internal, package-private class in java.lang. It has, among others, an exit() and a halt() methods. Its exit() method does some stuff to prevent the hooks from being executed twice, and so on, but basically, what it does is


  1. 运行系统挂钩。系统挂钩由JRE方法在内部注册。它们按顺序运行,而不是在线程中运行。第二个系统挂钩运行您添加的应用程序挂钩。它将每个作为一个线程启动,然后在最后为每个线程提供一个 join 。其他系统挂钩可以在应用程序挂钩之前或之后运行。

  2. 如果终结器应该在暂停之前运行,它们就会运行。这通常不会发生,因为该方法已被弃用。如果退出的状态为零,则无论如何都会忽略 runFinalizersOnExit

  3. JVM暂停。

  1. Run the System Hooks. The System Hooks are registered internally by JRE methods. They are ran sequentially, not in threads. The second system hook is what runs the application hooks that you have added. It starts each of them as a thread and then has a join for each of them at the end. Other system hooks may run before or after the application hooks.
  2. If finalizers are supposed to be ran prior to halting, they are ran. This should generally not even happen, as the method has been deprecated. And if the exit is with a status other than zero, it ignores the runFinalizersOnExit anyway.
  3. The JVM is halted.

现在,与您的假设相反,在第3阶段,所有线程都停止了。 halt 方法是原生的,我没有尝试读取本机代码,但是直到它被调用的那一刻,运行的唯一代码是纯Java,并且没有什么可以阻止其中任何地方的线程。 Runtime.addShutdownHook 实际上说:

Now, contrary to your supposition, it is at stage 3 that all the threads are stopped. The halt method is native, and I have not attempted to read the native code, but up to the moment it is called, the only code being ran is pure Java, and there is nothing that stops the threads anywhere in it. The documentation of Runtime.addShutdownHook says, in fact:


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

(强调我的)

所以你看,确实告诉线程他们应该离开他们的循环确实是关闭钩子的工作的一部分

So you see, it is indeed part of the shutdown hook's job to tell threads that they should leave their loops and clean up.

你的另一个误解就是给线程一个高优先级。高优先级并不意味着线程将在所有其他挂钩之前首先运行。它只是意味着每当操作系统必须决定哪些线程处于准备运行状态以给CPU运行时,高优先级线程将具有更高的获胜概率 - 取决于关于操作系统的调度算法。简而言之,它可能会获得更多的CPU访问权限,但它不会 - 特别是如果你有多个CPU核心 - 必须在其他线程之前启动或在它们之前完成。

Another misconception you have is about giving the thread a high priority. A high priority doesn't mean that the thread will run first, before all other hooks. It merely means that whenever the operating system has to make a decision which of the threads which are in "ready to run" state to give to a CPU to run, a high-priority thread will have a higher probability of "winning" - depending on the operating system's scheduling algorithm. In short, it may get a little more CPU access, but it will not - especially if you have more than one CPU core - necessarily start before other threads or complete before them.

最后一件事 - 如果你想用一个标志告诉一个线程停止工作,那个标志应该是 volatile

One last thing - if you want to use a flag to tell a thread to stop working, that flag should be volatile.

这篇关于JVM终止后会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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