怎么Java的系统。exit()工作尝试/赶/最终块?[重复]
-
05-07-2019 - |
题
这个问题已经有一个答案在这里:
- 没有一个最后框始终得到执行Java? 46的答案
我知道还有头痛,这涉及返回在尝试/赶/最终块-情况下返回的最后总是回返的方法,即使返回在尝试或抓块应该是一个执行。
然而,并同样适用于系统。exit()?例如,如果我有一个尝试块:
try {
//Code
System.exit(0)
}
catch (Exception ex) {
//Log the exception
}
finally {
System.exit(1)
}
如果没有例外情况,该系统。exit()将称为?如果出口是返回的发言,然后在线系统。exit(1)总会(?) 被称为。然而,我不知道,如果出口行为不同于返回。
代码是在一个极端的情况,是非常困难的,如果不是不可能的,再现,所以我不能写一个单元的测试。我要尝试运行一个试验之后的今天,如果我得到一个几分钟免费的,但我很好奇,反正,也许有人这么知道的答案,可以提供它之前或在的情况下,我不能运行一个实验。
解决方案
没有。 System.exit(0)
不返回,并且最终块不是执行。
System.exit(int)
可以扔掉一个 SecurityException
.如果发生这种情况,最后块 将 以执行。和由于相同的主要是呼吁相同的方法从相同的码基地,另一个 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);
}
}
}
其他提示
简单测试,包括 catch
太显示,如果 system.exit(0)
不会引发安全例外,它将是最后一次执行声明(catch
和 finally
不执行在所有)。
如果 system.exit(0)
不会扔一个安全例外, catch
和 finally
报表是执行。如果两个 catch
和 finally
含有 system.exit()
发言,只有前所作发言的这些 system.exit()
报表是执行。
在这两种情况下描述下所述,如果 try
代码属于一种方法称为通过另一种方法,称为方法不返回。
更多细节 在这里, (个人的博客).
其他的答案已经涵盖如何 catch
和 finally
块不行如果 System.exit
退出JVM没有扔 SecurityException
, 但他们不出现会发生什么情况在"尝试与资源"框要的资源:他们关闭了?
根据 捷尔思,部分14.20.3.2:
效果的翻译是把资源的规范"内部"的尝试的发言。这使得抓住条款的延长试图与资源的声明,以抓住的一个例外,由于自动初始化或关闭的任何资源。
此外,所有资源将有被关闭(或试图关闭)由当时的最后框执行,保持与意图的最后关键词。
那就是,资源将 close
d前 catch
或 finally
框运行。如果他们是什么 close
d即使以某种方式 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
在尝试与资源的发言。
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
成功。
最后,区块将被执行的不管是什么。...即使尽量块引发的任何抛出的(例外或误差)。....
唯一的情况下最后块不行...是的,当我们通话系统。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!!!");
}
它将不执行最后块。该程序将终止 之后系统。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*/ }
将必须进行更新。在这种情况下的图书馆,有定义的执行情况,他们将需要进行改装,也理解这种例外。
总的来说,这似乎是一个很好的战略我。有其他人在这里这么认为吗?
在面的例子中,如果
System.exit(0)
是之前的异常行,该程序将终止通常情况下,因此最终将不会执行。如果的
System.exix(0)
是最后一行中的试块,我们在这里有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