这个问题已经在这里有一个答案:
- 是否finally块总是得到Java的执行? 46个回答
我知道它会涉及到的try / catch / finally块返回头疼的 - 情况下,在最后的回报始终是方法的返回,即使在try或catch块一回应该执行的一个。
然而,也同样适用于System.exit()的? 举例来说,如果我有一个try块:
try {
//Code
System.exit(0)
}
catch (Exception ex) {
//Log the exception
}
finally {
System.exit(1)
}
如果没有异常,这System.exit()的会叫什么名字? 如果出口是一个return语句,那么该行System.exit(1)总是(?)被调用。 不过,我不知道,如果退出的行为与收益不同。
该代码是在这是非常困难的,如果不是不可能的,为了再现一个极端的例子,所以我不能写一个单元测试。 我要去尝试运行实验后的今天,如果我得到一些免费分钟,但我很好奇,无论如何,也许有人对SO知道答案,可以之前或在情况下,我不能运行它提供实验。
Answer 1:
号System.exit(0)
不返回,并且不执行最终块。
System.exit(int)
可以抛出一个SecurityException
。 如果出现这种情况,finally块将被执行。 而且,由于相同的主要是调用从相同的代码库相同的方法,另一个SecurityException
很可能是从第二个呼叫抛出。
下面是第二种情况的一个例子:
import java.security.Permission;
public class Main
{
public static void main(String... argv)
throws Exception
{
System.setSecurityManager(new SecurityManager() {
@Override
public void checkPermission(Permission perm)
{
/* Allow everything else. */
}
@Override
public void checkExit(int status)
{
/* Don't allow exit with any status code. */
throw new SecurityException();
}
});
System.err.println("I'm dying!");
try {
System.exit(0);
} finally {
System.err.println("I'm not dead yet!");
System.exit(1);
}
}
}
Answer 2:
简单的测试,包括catch
太透露,如果system.exit(0)
不会引发安全异常,这将是最后一个执行的语句( catch
和finally
根本不被执行)。
如果system.exit(0)
并抛出一个安全异常, catch
和finally
的语句被执行。 如果同时catch
和finally
包含system.exit()
语句,只有这些语句之前system.exit()
语句被执行。
在上面的描述下这两种情况下,如果try
代码属于通过其他方法调用的方法,调用的方法不返回。
更多细节在这里 (个人博客)。
Answer 3:
其他答案已经介绍如何catch
和finally
如果块不运行System.exit
退出JVM没有抛出SecurityException
,但他们没有表现出一个“尝试-与资源”区块的资源会发生什么:他们是关闭?
按照JLS,第14.20.3.2 :
翻译的作用是把资源规范“内部” try语句。 这允许扩展的尝试,与资源语句来捕捉异常的catch子句所导致的任何资源的自动初始化或关闭。
此外,所有的资源将被关闭(或试图闭合)由执行最后块的时间,以与的意图保持最后关键字。
也就是说,资源将close
d一个之前catch
或finally
阻止运行。 如果他们是close
Ð不知何故,即使catch
并finally
不跑?
下面是一些代码,以证明在“尝试与 - 资源”的语句资源也不关闭。
我用一个简单的子类BufferedReader
,调用之前打印一份声明super.close
。
class TestBufferedReader extends BufferedReader {
public TestBufferedReader(Reader r) {
super(r);
}
@Override
public void close() throws IOException {
System.out.println("close!");
super.close();
}
}
然后,我设置了呼叫的测试用例System.exit
在try-与资源的语句。
public static void main(String[] args)
{
try (BufferedReader reader = new TestBufferedReader(new InputStreamReader(System.in)))
{
System.out.println("In try");
System.exit(0);
}
catch (Exception e)
{
System.out.println("Exception of type " + e.getClass().getName() + " caught: " + e.getMessage());
}
finally
{
System.out.println("finally!");
}
}
输出:
在试
因此,不仅catch
并finally
块无法运行,一个“尝试与-资源”的语句将没有机会来close
它的资源,如果System.exit
成功。
Answer 4:
finally块将不管执行的....即使try块抛出任何抛出(异常或错误)......
唯一的案件finally块不执行......当我们调用System.exit()方法..
try{
System.out.println("I am in try block");
System.exit(1);
} catch(Exception ex){
ex.printStackTrace();
} finally {
System.out.println("I am in finally block!!!");
}
它不会执行finally块。 该计划将后System.exit()的语句被终止。
Answer 5:
如果您认为这种行为有问题,你需要很好地控制你的System.exit
电话,那么你可以做的唯一的事情是在你自己的逻辑绕了System.exit功能。 如果我们这样做,我们可以得到最终的执行块,并获得资源封闭,我们的出口流的一部分。
我正在考虑做的是包裹System.exit
调用和功能在我自己的静态方法。 我在执行的exit
我会抛出的自定义子类Throwable
或Error
,并实现了自定义的未捕获异常处理程序Thread.setDefaultUncaughtExceptionHandler
来处理异常。 因此,我的代码就变成了:
//in initialization logic:
Thread.setDefaultUncaughtExceptionHandler((thread, exception) -> {
if(exception instanceof SystemExitEvent){
System.exit(((SystemExitEvent)exception).exitCode);
}
})
// in "main flow" or "close button" or whatever
public void mainFlow(){
try {
businessLogic();
Utilities.exit(0);
}
finally {
cleanUpFileSystemOrDatabaseConnectionOrWhatever();
}
}
//...
class Utilities {
// I'm not a fan of documentaiton,
// but this method could use it.
public void exit(int exitCode){
throw new SystemExitEvent(exitCode);
}
}
class SystemExitEvent extends Throwable {
private final int exitCode;
public SystemExitEvent(int exitCode){
super("system is shutting down")
this.exitCode = exitCode;
}
}
这种策略使得该逻辑可测试的附加“利”:来测试包含我们的“主流”的方法实际上是要求系统退出,我们所要做的就是赶上抛出并断言是写类型。 例如,对于我们的业务逻辑封装测试可能类似于:
//kotlin, a really nice language particularly for testing on the JVM!
@Test fun `when calling business logic should business the business`(){
//setup
val underTest = makeComponentUnderTest(configureToReturnExitCode = 42);
//act
val thrown: SystemExitEvent = try {
underTest.mainFlow();
fail("System Exit event not thrown!")
}
catch(event: SystemExitEvent){
event;
}
//assert
assertThat(thrown.exitCode).isEqualTo(42)
主要缺点这种策略是,它是让出功能异常流动,往往已意想不到的后果的一种方式。 最明显的一个,在这种情况下,是任何地方,你已经写了try { ... } catch(Throwable ex){ /*doesnt rethrow*/ }
将不得不进行更新。 在具有自定义执行上下文库的情况下,他们将需要进行改装也明白这一点例外。
总的来说,这似乎是一个很好的策略给我。 有没有人在这里这样认为吗?
Answer 6:
在下面的例子中,如果System.exit(0)
是个例外行之前,该程序将被正常终止,所以最终将不会执行。
如果System.exix(0)
是try块的最后一行,在这里我们有2个场景
- 当异常存在,则最后被执行块
- 当异常是不存在,则最终,不执行块
。
package com.exception;
public class UserDefind extends Exception {
private static int accno[] = {1001,1002,1003,1004,1005};
private static String name[] = {"raju","ramu","gopi","baby","bunny"};
private static double bal[] = {9000.00,5675.27,3000.00,1999.00,1600.00};
UserDefind(){}
UserDefind(String str){
super(str);
}
public static void main(String[] args) {
try {
//System.exit(0); -------------LINE 1---------------------------------
System.out.println("accno"+"\t"+"name"+"\t"+"balance");
for (int i = 0; i < 5; i++) {
System.out.println(accno[i]+"\t"+name[i]+"\t"+bal[i]);
//rise exception if balance < 2000
if (bal[i] < 200) {
UserDefind ue = new UserDefind("Balance amount Less");
throw ue;
}//end if
}//end for
//System.exit(0);-------------LINE 2---------------------------------
}//end try
catch (UserDefind ue)
{
System.out.println(ue);
}
finally{
System.out.println("Finnaly");
System.out.println("Finnaly");
System.out.println("Finnaly");
}
}//end of main
}//end of class
文章来源: How does Java's System.exit() work with try/catch/finally blocks? [duplicate]