이 질문에는 이미 답변이 있습니다.
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 ()이 호출됩니까? exit가 return 문인 경우 System.exit (1) 줄이 항상 호출 (?)됩니다. 그러나 출구가 반환과 다르게 동작하는지 확실하지 않습니다.
코드는 극단적 인 경우 재현하기가 불가능하지는 않더라도 매우 어렵 기 때문에 단위 테스트를 작성할 수 없습니다. 나는 나중에 약간의 자유 분을 얻으려고 나중에 실험을하려고 노력할 것이다. 그러나 어쨌든 나는 호기심이 많다. 아마도 누군가가 그 대답을 알고 있고 그것을 제공 할 수있다. 실험.
아니.System.exit(0)
반환하지 않으며 finally 블록이 실행되지 않습니다.
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);
}
}
}
StackOverflowException
을 예방하기 위해System.exit
스택 프레임이 호출되면System.exit
스택 한도 바로 앞에 있습니다. 이러한 종류의 경계 조건은 때때로 해커에 의해 조작 될 수 있으므로이 문제에 의존하는 보안 불변성이있는 경우Thread.UncaughtExceptionHandler
그것은 깊이있는 방어 수단으로 존재합니다. - Mike Samuelfinally
실행중인 블록 (ifAnt
개미에 의존하는 응용 프로그램 시작 스크립트로 사용하고 있습니다.java
작업) 또는 실행되지 않는 경우 (응용 프로그램이java
콘솔에서Ant
). 이 답변을 기반으로 볼 때 응용 프로그램이 Ant의 내부에서 호출 될 때java
과제 aSecurityException
던졌습니다. - Marcus Junius BrutusStackOverflowException
(당신이 정의하지 않는 한) 존재하지 않습니다. 그것은StackOverflowError
. 중요한 작은 차이. - Peter Verhas
다음을 포함한 간단한 테스트catch
ifsystem.exit(0)
보안 예외를 throw하지 않습니다. 마지막으로 실행 된 명령문이됩니다.catch
과finally
전혀 실행되지 않습니다).
만약system.exit(0)
보안 예외를 throw합니다.catch
과finally
명령.이 실행됩니다. 둘 다catch
과finally
있다system.exit()
진술, 이보다 앞선 진술system.exit()
명령.이 실행됩니다.
위의 두 경우 모두에서try
코드가 다른 메서드에서 호출 한 메서드에 속하므로 호출 된 메서드가 반환되지 않습니다.
자세한 내용은이리(개인 블로그).
다른 해답은catch
과finally
블록이 실행되지 않는 경우System.exit
던지지 않고 JVM을 종료합니다.SecurityException
, 자원에 대한 "자원과 함께 시도"블록에서 어떤 일이 일어나는지 보여주지는 않습니다.
에 따르면JLS, 섹션 14.20.3.2:
변환의 효과는 자원 스펙을 "내부"try 문에 넣는 것입니다. 이를 통해 확장 된 try-with-resources 문의 catch 절을 사용하여 자원의 자동 초기화 또는 닫기로 인해 예외를 catch 할 수 있습니다.
또한 finally 블록의 의도에 따라 finally 블록이 실행될 때까지 모든 리소스가 닫혔습니다 (닫히기도합니다).
즉, 자원은close
전에 dcatch
또는finally
블록 실행. 그들이 어때?close
어쨌든catch
과finally
도망 간다?
"try-with-resources"문에있는 리소스가 닫히지 않았 음을 입증하는 코드가 있습니다.
나는 간단한 서브 클래스를 사용한다.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-with-resources 문에서.
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
블록이 실행되지 않으면 "try-with-resources"문이 실행되지 않습니다.close
그 자원System.exit
성공합니다.
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 () 문 다음에.
이 문제가 문제가되는 것으로 생각하고System.exit
호출하면 System.exit 기능을 자신의 논리에 랩핑하면됩니다. 그렇게하면 최종 블록을 실행하고 종료 흐름의 일부로 리소스를 닫을 수 있습니다.
내가하고있는 일은System.exit
전화 & amp; 기능을 내 정적 메서드입니다. 내 구현에exit
나는 사용자 정의 서브 클래스를 던질 것이다.Throwable
또는Error
다음과 같이 사용자 정의 Uncaught 예외 처리기를 구현합니다.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;
}
}
이 전략은이 로직을 테스트 가능하게 만드는 "이점"을 추가했습니다. "메인 플로우"를 포함하는 메소드가 실제로 시스템을 종료하도록 테스트하려면, 우리가해야 할 일은 throwable을 잡아서 쓰기 유형이라고 주장하는 것입니다. 예를 들어 비즈니스 로직 래퍼에 대한 테스트는 다음과 같습니다.
//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*/ }
업데이트해야합니다. 사용자 정의 실행 컨텍스트가있는 라이브러리의 경우이 예외를 이해하기 위해 개조해야합니다.
균형을 이룰 수있는 좋은 전략 인 것 같습니다. 다른 사람들이 그렇게 생각하니?
아래 예에서 ifSystem.exit(0)
예외 행 앞에 있으면 프로그램이 정상적으로 종료되므로 FINALLY가 실행되지 않습니다.
만약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
throw new Exception("Error");
바로 전에System.exit(0)
실행 파일이 반환하는 상태 코드를 컴파일하고 봅니다. - Ki Jéy