uck*_*man 20 java exit processbuilder
我有一个Java程序,它是ProcessBuilder从另一个Java程序启动的.
System.exit(0)从子程序调用,但对于我们的一些用户(在Windows上),java.exe与子项关联的进程不会终止.子程序没有关闭挂钩,也没有SecurityManager可能停止System.exit()终止VM的挂钩.我无法在Linux或Windows Vista上自行重现此问题.到目前为止,问题的唯一报告来自两个Windows XP用户和一个Vista用户,使用两个不同的JRE(1.6.0_15和1.6.0_18),但他们每次都能够重现问题.
任何人都可以提出为什么JVM无法在之后终止System.exit(),然后只在某些机器上终止的原因?
编辑1:我让用户安装JDK,这样我们就可以从违规的虚拟机中获取一个线程转储.用户告诉我的是,一旦他点击我的菜单中的"退出"项目,VM进程就会从VisualVM中消失---但是,根据Windows任务管理器,该进程尚未终止,无论多长时间用户等待(分钟,小时),它永远不会终止.
编辑2:我现在已经确认Process.waitFor()在父程序中永远不会返回至少一个有问题的用户.总而言之:孩子VM似乎已经死了(VisualVM甚至没有看到它),但是父母仍然认为这个过程是实时的,Windows也是如此.
如果您的代码(或您使用的库)具有关闭钩子或终结器未完全完成,则会发生这种情况.
一个更有活力(所以应该只在极端情况下使用!)强制关机的方法是运行:
Runtime.getRuntime().halt(0);
Run Code Online (Sandbox Code Playgroud)
小智 6
父进程有一个专用于使用子进程STDOUT和STDERR(将该输出传递给日志文件)的线程.据我所知,这些工作正常,因为我们看到了我们期望在日志中看到的所有输出
当我使用stdout/stderr时,我的程序没有从任务mgr中消失,我遇到了类似的问题.在我的情况下,如果我在调用system.exit()之前关闭了正在侦听的流,那么javaw.exe就会挂起.奇怪的是,它没有写入流...
在我的情况下,解决方案是简单地刷新流而不是在存在之前关闭它.当然,你可以随时刷新然后在退出之前重定向回stdout和stderr.
检查是否存在死锁。
例如,
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
System.exit(1);
Run Code Online (Sandbox Code Playgroud)
并在close()
public void close() {
// some code
System.exit(1);
}
Run Code Online (Sandbox Code Playgroud)
实际上System.exit()调用关闭钩子和终结器。因此,如果您的 shutdown 钩子出于某种原因在内部再次调用 exit() (例如,当引发close()您想要退出程序的异常时,那么您也会exit()在那里调用)。像这样..
public void close() {
try {
// some code that raises exception which requires to exit the program
} catch(Exception exceptionWhichWhenOccurredShouldExitProgram) {
log.error(exceptionWhichWhenOccurredShouldExitProgram);
System.exit(1);
}
}
Run Code Online (Sandbox Code Playgroud)
虽然抛出异常是一个很好的做法,但有些人可能会选择记录并退出。
另请注意,
Ctrl+C如果存在死锁,这也将不起作用。因为它还调用关闭挂钩。
无论如何,如果是这种情况,可以通过以下解决方法解决问题:
private static AtomicBoolean exitCalled=new AtomicBoolean();
private static void exit(int status) {
if(!exitCalled.get()) {
exitCalled.set(true);
System.exit(status);
}
}
Runtime.getRuntime().addShutdownHook(new Thread(MyClass::close));
exit(1);
}
private static void close() {
exit(1);
}
Run Code Online (Sandbox Code Playgroud)
PS:我觉得上面的
exit()版本实际上必须只写在System.exit()方法中(可能是 JDK 的一些 PR?)因为,实际上没有任何意义(至少从我看来)System.exit()
| 归档时间: |
|
| 查看次数: |
27720 次 |
| 最近记录: |