如果在JVM关闭已经在进行中时再次调用System.exit()会发生什么?

7

这是不操作吗?JVM会避免再次调用关闭挂钩吗?

对于一个使用案例,考虑一个UncaughtExceptionHandler,它为SomeException调用System.exit(),然后在短时间内在两个单独的线程中抛出SomeException。

此外,假设在新线程中调用System.exit()以避免潜在的死锁。

更新

正如其中一条评论正确指出的那样,我应该自己测试,但我太懒了。下面的测试无论是在常规线程还是守护线程中调用System.exit()都可以成功完成,并在打印后以代码1退出:

Requesting shutdown ...
Shutdown started ...
Requesting shutdown ...
Shutdown completed ...

这里是代码:

public class ConcurrentSystemExit {

  private final static boolean DAEMON = false;

  public static void main(String[] args) throws InterruptedException {

    // Register a shutdown hook that waits 6 secs
    Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {
        try {
          System.out.println("Shutdown started ...");
          Thread.sleep(6000);
          System.out.println("Shutdown completed ...");
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    });

    // Define a Thread that calls exit()
    class ShutdownThread extends Thread {
      public void run() {
        System.out.println("Requesting shutdown ...");
        System.exit(1);
      }
    }

    // Issue first exit()
    Thread t1 = new ShutdownThread();
    t1.setDaemon(DAEMON);
    t1.start();

    Thread.sleep(3000);

    // Issue second exit()
    Thread t2 = new ShutdownThread();
    t2.setDaemon(DAEMON);
    t2.start();
  }
}

4
你尝试过测试吗? - MadProgrammer
System.exit 立即停止 JVM。没有 "然后"。除非您是从一个关闭挂钩调用它?在这种情况下,我怀疑您将进入递归调用,导致堆栈溢出。 - MadConan
@arshajii:在你回复的时候我编辑了我的评论。 - MadConan
System.exit() 不会立即停止。它会调用关闭挂钩,这可能需要一些时间,具体取决于您在那里执行的操作。例如,它们可能会等待长时间的数据库查询完成。 - Bogdan Calmac
糟糕!我的错。我脚的味道像鸡肉。 - MadConan
显示剩余2条评论
2个回答

5
JavaDoc 中了解到 Runtime.exit() 的作用:
如果在虚拟机开始关闭序列后调用此方法,则如果正在运行关闭挂钩,则此方法将无限期地阻塞。 如果已经运行了关闭挂钩并启用了退出终止,则如果状态为非零,则此方法使用给定的状态代码停止虚拟机; 否则,它将无限期地阻塞。

从这里我可以推断出,关闭挂钩不会再次被调用,只要它在一个单独的守护线程中被调用,不会阻止JVM在被阻塞时终止,因此可以多次调用exit()。 - Bogdan Calmac
我认为没有任何线程会阻止JVM终止。 - Dolda2000
正确。一旦调用exit(),各个线程的守护进程状态就无关紧要了。JVM只会等待关闭挂钩完成。 - Bogdan Calmac

0

仅供参考,exit()方法可能会抛出SecurityException异常。

如果存在安全管理器且其checkExit方法不允许使用指定状态退出,则会抛出SecurityException异常。

系统 (Java平台SE 7)

如果在JVM关闭已经在进行中的情况下再次调用System.exit()会发生什么?

这取决于安全上下文,但在大多数情况下,在调用exit方法后,不会执行任何操作,它只是终止JVM。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接