当SecurityManager.checkExit抛出异常时,System.exit(0)不会阻止最终被调用

时间:2016-06-17 07:41:26

标签: java

我对System.exit(0);有疑问。 当我尝试下面的代码时,由于System.exit(0);

,输出无效
String number = "12345M";
try {
    System.exit(0);
} catch (Exception e) {
    System.out.println("Exception caught");
} finally {
    System.out.println("inside finally");
}

但是当我尝试以下代码时:

System.setSecurityManager(new SecurityManager() {
    @Override
    public void checkExit(int status) {
        throw new ThreadDeath();
    }
});

try {
    System.exit(0);
} finally {
    System.out.println("I am  finally block");
}

输出结果为:

  

我终于阻止了

有人可以解释一下这种不同的行为吗?

4 个答案:

答案 0 :(得分:20)

exit例外阻止了ThreadDeath(这不是一个你应该自己扔掉的人):

  

SecurityException - 如果存在安全管理器且其checkExit方法不允许以指定状态退出。

https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#exit(int)

请注意,您应该抛出SecurityException以防止退出,例如:

System.setSecurityManager(new SecurityManager() {
    @Override
    public void checkExit(int status) {
        throw new SecurityException("Not allowed.");
    }
});

try {
    System.exit(0);
} catch(SecurityException e) {
    System.out.println("Exit failed.");
} finally {
    System.out.println("I am finally block");
}
System.out.println("Program still running");

输出:

Exit failed.
I am finally block
Program still running

答案 1 :(得分:4)

当你在不覆盖System.exit()方法的情况下调用checkExit()时,JVM会在此时暂停,最后不会被调用。

但是,当您覆盖checkExit()方法时,抛出异常并最终调用。

答案 2 :(得分:3)

Quoting

  

java.lang.SecurityManager类允许应用程序实现安全策略。它允许应用程序在执行可能不安全或敏感的操作之前确定操作是什么以及是否在允许执行操作的安全上下文中尝试操作。应用程序可以允许或禁止操作。

在上面的代码中,checkExit确定操作是否允许操作并且通常是否有效并因此退出。由于抛出异常,因此确定操作不安全并且防止执行。

请参阅http://www.tutorialspoint.com/java/lang/system_exit.htm

答案 3 :(得分:2)

System.exit(0);是一个被调用的,它将随后调用Runtime.exit,它将检查是否附加了SecurityManager。 如果附加了一个,它将执行checkExit方法。

查看Runtime.exit中的代码:

public void exit(int status) {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkExit(status);
    }
    Shutdown.exit(status);
}

因此,在您的代码中,当您调用System.exit(0);时系统实际上不会退出,因为您在SecurityManager.checkExit

中抛出异常

永远不会调用Shutdown.exit(status);,VM也不会停止,它将继续执行任何语句,然后它将到达main方法的末尾并终止。

改变你这样的代码并玩游戏

System.setSecurityManager(new SecurityManager() {
                              @Override
                              public void checkExit(int status) {

                                  if(status == 0){
                                      System.out.println("Not going to finally");
                                  }else{
                                      throw new SecurityException();
                                  }

                              }
                          });

    try {
        System.exit(1);

    } catch (Exception e){
        e.printStackTrace();
    }finally {
        System.out.println("I am  finally block");
    }

    System.out.println("System.exit(1) Didn't work ......");

}

查看System.exit java doc和Runtime.exit doc