public static void main(String[] args) {
ThreadTest t = new ThreadTest();
t.test2();
}
// jvm什么时候推出
@Test
public void test2() {
// 除直接kill,其它JVM终止都会调用该钩子
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("关闭JVM");
}
});
Thread t = new Thread() {
@Override
public void run() {
System.out.println("用户线程正在运行....");
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("用户线程结束....");
}
};
t.setDaemon(false);
//如果是false,JVM会等到最用一个用户线程跑完才执行终止操作,JVM自动调用Shutdown,用户也可以自行调用System.exit(0)
//如果是true,说明是守护线程,JVM任务是辅助用的,可有可无,JVM不会等待该线程
t.start();
System.out.println("程序执行完毕");
}
在eclipse中运行,如果是通过Junit的方式测试运行test2方法,是模拟不出来预想的情况的。直接就退出了,为什么呢?看下Eclipse调用Junit的入口代码就知道了
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(String[])
try {
RemoteTestRunner testRunServer= new RemoteTestRunner();
testRunServer.init(args);
testRunServer.run();
} catch (Throwable e) {
e.printStackTrace(); // don't allow System.exit(0) to swallow exceptions
} finally {
// fix for 14434
System.exit(0);
}
这里显示的调用了退出方法。所以JVM就直接退出并释放资源。
在自己的main函数中由于自己没有主动调用System.exit(0);
把处理权交给了JVM,JVM在退出前会等待所有的用户线程都关闭掉。
public static void main(String[] args) {
ThreadTest t = new ThreadTest();
t.test2();
throw new RuntimeException("xxx");
}
及时main线程抛出异常,JVM一样会等待...
java.c 这块处理的源码
/* * Always detach the main thread so that it appears to have ended when * the application's main method exits. This will invoke the * uncaught exception handler machinery if main threw an * exception. An uncaught exception handler cannot change the * launcher's return code except by calling System.exit. * * Wait for all non-daemon threads to end, then destroy the VM. * This will actually create a trivial new Java waiter thread * named "DestroyJavaVM", but this will be seen as a different * thread from the one that executed main, even though they are * the same C thread. This allows mainThread.join() and * mainThread.isAlive() to work as expected. */ #define LEAVE() \ if ((*vm)->DetachCurrentThread(vm) != 0) { \ JLI_ReportErrorMessage(JVM_ERROR2); \ ret = 1; \ } \ (*vm)->DestroyJavaVM(vm); \ return ret \