System.exit(0) не предотвращает окончательного вызова, когда SecurityManager.checkExit выдает исключение
У меня проблема с 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");
}
Выход был:
Я наконец-то блокирую
Может кто-нибудь объяснить это другое поведение?
Ответы
Ответ 1
Поскольку 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
Ответ 2
Когда вы вызываете System.exit()
без переопределения метода checkExit()
, JVM останавливается в этой точке и, наконец, не вызывается.
Однако, когда вы переопределяете метод checkExit()
, исключение вызывается и, наконец, вызывается.
Ответ 3
Цитата:
Класс java.lang.SecurityManager позволяет приложениям применять политику безопасности. Он позволяет приложению определять, перед выполнением, возможно, небезопасной или чувствительной операции, что такое операция и предпринимается ли она в контексте безопасности, который позволяет выполнять операцию. Приложение может разрешить или запретить операцию.
В приведенном выше коде checkExit определяет, может ли операция работать и нормально работать, и, таким образом, выйти. Поскольку выбрано исключение, операция, таким образом, определяется небезопасно и предотвращается.
Пожалуйста, обратитесь http://www.tutorialspoint.com/java/lang/system_exit.htm
Ответ 4
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);
никогда не вызывается, и виртуальная машина не останавливается, и она будет продолжать выполнять любые операторы, а затем дойдет до конца основного метода и завершает работу.
Измените код таким образом и поиграйте
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