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