- 如果我正确理解了每个 java 进程都与一个单独的 JVM 实例相关联,并且每个 JVM 实例都由操作系统提供一个堆内存,操作系统也会在 JVM 终止时重新收集该堆内存。
So on termination even if there were some memory leaks all the memory will be reclaimed by the OS(Please correct if I have mistaken)
. - 如果第 1 点是真的,为什么我们必须使用关闭挂钩。谷歌搜索后,主要建议释放所有资源并正常关闭。
Even if it does not gracefully shutdown all the memory and resources would be freed?
- 我写了一个简单的关机钩子。在我的主线程中,我正在运行一个无限循环,然后使用中的终止按钮终止进程
Eclipse
。但是关闭钩子线程没有运行。Eclipse 中的终止进程是否会Runtime.getRuntime().halt(status)
因为 AFAIK 突然终止 JVM 而未执行关闭挂钩而调用? 最后,如果我的主要代码如下 -
public static void main(String args[]){ Runtime.getRuntime().addShutdownHook(new Thread(new ShutDownHook())); System.out.println("Shutdown hook registered"); System.out.println("Before calling exit"); System.exit(0); System.out.println("After exit"); }
为什么
After exit
不打印?当关闭钩子正在执行时,主线程必须继续进一步执行并打印After exit
?
1 回答
1)你是对的。
2) Java 进程的内存将被回收,但您可能需要进行其他清理,例如删除一些临时文件。
3)让我们去的javadocRuntime#addShutdownHook(Thread)
Java 虚拟机关闭以响应两种事件:
程序正常退出,当最后一个非守护线程退出或调用 exit(等效于 System.exit)方法时,或
虚拟机响应用户中断(例如键入 ^C)或系统范围的事件(例如用户注销或系统关闭)而终止。
您必须查看 Eclipse 的源代码,但 Eclipse 似乎终止了进程,而不是发送System.exit(..)
或发送用户中断。这可能会越过 JVM,因此不会执行关闭挂钩。
4)您添加的关闭挂钩Runtime#addShutdownHook(Thread)
被添加static
IdentityHashMap
到ApplicationShutdownHooks
. 此类在如下所示Shutdown
的初始化程序块中向该类注册其自己的关闭挂钩static
static {
try {
Shutdown.add(1 /* shutdown hook invocation order */,
false /* not registered if shutdown in progress */,
new Runnable() {
public void run() {
runHooks();
}
}
);
hooks = new IdentityHashMap<>();
} catch (IllegalStateException e) {
// application shutdown hooks cannot be added if
// shutdown is in progress.
hooks = null;
}
}
runHooks()
方法是
static void runHooks() {
Collection<Thread> threads;
synchronized(ApplicationShutdownHooks.class) {
threads = hooks.keySet();
hooks = null;
}
for (Thread hook : threads) {
hook.start();
}
for (Thread hook : threads) {
try {
hook.join();
} catch (InterruptedException x) { }
}
}
所以当前线程加入了所有其他线程。
什么时候
System.exit(0);
被调用,在某处Shutdown.sequence()
被调用,调用Shutdown.hooks()
实现为
private static void runHooks() {
for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
try {
Runnable hook;
synchronized (lock) {
// acquire the lock to make sure the hook registered during
// shutdown is visible here.
currentRunningHook = i;
hook = hooks[i];
}
if (hook != null) hook.run();
} catch(Throwable t) {
if (t instanceof ThreadDeath) {
ThreadDeath td = (ThreadDeath)t;
throw td;
}
}
}
}
其中一个Runnable
对象hooks
就是我上面描述的。它不会产生新的Thread
,它会与run()
.
一旦Shutdown.sequence()
完成,系统就真的退出了,所以 finalSystem.out.println()
不会执行。