如何在 finally 块中调用 System.exit(0) 后运行代码
Posted
技术标签:
【中文标题】如何在 finally 块中调用 System.exit(0) 后运行代码【英文标题】:How to run code after a call to Sytem.exit(0) in a finally block 【发布时间】:2012-01-04 16:53:47 【问题描述】:我有三个类,分别是 alpha、beta、gamma,这三个类中的每一个都有一个 main
方法。
alpha 和 beta 类在它们的 main
方法中都有一个 try...catch...finally
块,例如:
public class alpha
public static void main(String[] args)
try
Do something;
catch(Exception ex)
ex.printStackTrace();
finally
System.exit(0);
public class beta
public static void main(String[] args)
try
Do something;
catch(Exception ex)
ex.printStackTrace();
finally
System.exit(0);
现在在 gamma 类中,我调用 alpha 和 beta 类的主要方法来连续运行,如下所示
public gamma
public static void main(String[] args)
try
alpha.main(arg);
beta.main(arg1);
catch (Exception e)
e.printStackTrace();
问题在于,由于 alpha 类的 finally
块内的 System.exit(0)
,永远无法到达代码 beta.main(arg1)
。
由于 alpha 和 beta 在单独执行时是独立的应用程序,因此它们应该在程序结束时终止服务。
所以现在有任何方法可以到达beta.main(arg1)
行,而不会对 alpha 和 beta 类的实际功能进行太多更改。
如果您需要更多详细信息,请告诉我。 提前谢谢...
【问题讨论】:
Preventing System.exit() from API 的可能重复项 【参考方案1】:在这种情况下,可以使用关闭钩子:
public class Gamma
public static void main(String[] args)
try
Thread hook = new Thread() public void run() Beta.main(args); ;
hook.setDaemon(true);
Runtime.getRuntime().addShutdownHook(hook);
Alpha.main(args);
catch (Exception e)
e.printStackTrace();
【讨论】:
不错。我从来没有想过使用关闭挂钩作为延续机制。 嗨弗拉德...我还有一个查询...当 alpha.main(args) 和 beta.main(args) 都执行时如何结束您的代码服务。??在此先感谢... 您的程序执行得非常完美,就像我想要的那样,但只有一个问题是伽玛类应该在执行您的语法后结束服务(与 System.exit(0) 相同)。你能帮上忙吗……?谢谢... 很好...我已经更新了代码。钩子线程应该是守护进程,不会阻塞最终的 System.exit(0)。 嗨,弗拉德,感谢您的回复......即使将守护进程设置为 true,程序也不会终止。您的代码是否缺少某些内容..请帮帮我。谢谢...【参考方案2】:(理想情况下,作为模块公共 API 的一部分的任何东西都不应该做任何调用 exit
的事情,并且类的 main
方法应该只是一个小 shim,它调用之前完成实际工作的其他东西生成正确的退出代码。)
也就是说,如果您想阻止System.exit
,您可以注册一个SecurityManager
,它将对System.exit
的调用转换为SecurityException
s 或Error
s。
System.exit
:
投掷
SecurityException
- 如果存在安全管理器并且其checkExit
方法不允许以指定状态退出。
类似
System.setSecurityManager(new SecurityManager()
@Override
public void checkExit(int exitCode) throws SecurityException
throw new SecurityException("stop that");
);
然后调用主方法的方法可以捕获并抑制SecurityException
。您可以通过创建自己的 ExitCalledError
并抛出它并仅抑制它来使其更健壮。
我发现这对于防止单元测试运行器在测试运行器被测试代码exit
ed 且退出代码为零时虚假地报告成功非常有用。
【讨论】:
嗯。我无法决定我对此的看法——我讨厌使用 SecurityManager 来做与安全无关的事情,但这是一种优雅的 hack。 @CharlieMartin,我同意这是一个 hack。不过,随着黑客攻击的进行,它相当强大,并且一些担忧,即测试运行者反馈的可靠性,保证了它的 IMO。当然也有问题——SecurityManager
的存在可能会引起库代码中的细微错误,并可能影响 VM 优化事物的方式。
好吧,我赞成。不过我还没有决定我的想法。【参考方案3】:
真的,唯一的解决方案是摆脱 System.exit() 调用。这就是为什么 System.exit() 是邪恶的。替换它们的一个好方法是抛出一个异常——你可以向系统添加一个异常处理程序(考虑将它们添加到 ThreadGroups 为每个异常路径添加一个),然后决定你想要做什么。
【讨论】:
【参考方案4】:System.exit(0)
终止当前运行的 Java 虚拟机。它会关闭 VM 上的所有应用程序,而不仅仅是调用System.exit(0)
的应用程序。您需要为您的功能考虑替代方案。这是一个关于它的链接。 System.exit usage
【讨论】:
以上是关于如何在 finally 块中调用 System.exit(0) 后运行代码的主要内容,如果未能解决你的问题,请参考以下文章
JAVA语言如何进行异常处理,关键字throws,throw,try,catch,finally分别代表啥意义在try块中抛出异常吗
JAVA 语言如何进行异常处理,关键字: throws,throw,try,catch,finally分别代表什么意义? 在try块中可以抛 出异常吗?