Java의 System.exit ()는 try / catch / finally 블록과 어떻게 작동합니까?
이 질문에 이미 답변이 있습니다.
try / catch / finally 블록에서 반환하는 것과 관련된 골칫거리를 알고 있습니다. try 또는 catch 블록의 반환이 실행되어야하는 경우에도 finally의 반환이 항상 메서드에 대한 반환 인 경우입니다.
그러나 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) 줄은 항상 (?) 호출됩니다. 그러나 exit가 return과 다르게 작동하는지 확실하지 않습니다.
코드는 불가능하지는 않지만 재현하기가 매우 어려운 극단적 인 경우이므로 단위 테스트를 작성할 수 없습니다. 나는 오늘 나중에 실험을 시도 할 것입니다. 몇 분의 여유 시간이 있으면 어쨌든 궁금합니다. 아마도 SO의 누군가가 답을 알고 답을 제공 할 수 있습니다. 실험.
아니오. System.exit(0)
반환되지 않으며 finally 블록은 실행되지 않습니다.
System.exit(int)
던질 수 있습니다 SecurityException
. 이 경우 finally 블록 이 실행됩니다. 그리고 동일한 주체가 동일한 코드베이스에서 동일한 메서드를 호출하기 SecurityException
때문에 두 번째 호출에서 다른 메서드 가 throw 될 가능성이 있습니다.
두 번째 경우의 예는 다음과 같습니다.
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)
보안 예외를 throw하지 않습니다, 그것은 마지막으로 실행 된 문을 것입니다 ( catch
와 finally
전혀 실행되지 않습니다).
If system.exit(0)
보안 예외가 발생 catch
하고 finally
명령문이 실행됩니다. 두 경우 catch
와는 finally
포함 system.exit()
문이 앞의 문에만 system.exit()
문이 실행됩니다.
위에서 설명한 두 경우 모두 try
코드가 다른 메서드에서 호출 된 메서드에 속하면 호출 된 메서드가 반환되지 않습니다.
다른 답변 은를 던지지 않고 JVM을 종료하는 경우 catch
및 finally
블록이 실행되지 않는 방법을 다루었 지만 리소스에 대한 "try-with-resources"블록에서 어떤 일이 발생하는지 보여주지 않습니다. 닫혀 있습니까?System.exit
SecurityException
JLS, 섹션 14.20.3.2 에 따르면 :
변환의 효과는 리소스 사양을 try 문 "내부"에 넣는 것입니다. 이렇게하면 확장 된 try-with-resources 문의 catch 절이 리소스의 자동 초기화 또는 닫기로 인해 예외를 포착 할 수 있습니다.
또한 finally 키워드의 의도에 따라 finally 블록이 실행될 때 모든 리소스가 닫히거나 닫히려고 시도됩니다.
즉, 또는 블록이 실행 close
되기 전에 리소스가 d 가됩니다. 그들은 무엇을하는 경우 경우에도 어떻게 든 거라고 및 실행되지 않습니다?catch
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!");
}
}
산출:
시도 중
따라서 do catch
및 finally
블록이 실행 되지 않을뿐만 아니라 "try-with-resources"문이 성공하면 close
리소스에 대한 기회를 얻지 못합니다 System.exit
.
finally 블록은 무슨 일이 있어도 실행됩니다 .... try 블록이 throwable (예외 또는 오류)을 던지더라도 .....
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
내 자신의 정적 메서드에서 호출 및 기능을 래핑하는 것입니다. 내 구현에서 또는 exit
의 사용자 지정 하위 클래스를 throw하고 해당 예외를 처리하기 위해 사용자 지정 Uncaught 예외 처리기를 구현합니다 . 따라서 내 코드는 다음과 같습니다.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;
}
}
This strategy has the added "benefit" of making this logic testable: to test that the method containing our "main flow" actually requests the system to exit, all we have to do is catch a throwable and assert that is the write type. For example, a test for our business logic wrapper might look like:
//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)
The major downside to this strategy is that it is a way of getting functionality out of exception flow, which often has unintended consequences. The most obvious one, in this case, is that anywhere you've written try { ... } catch(Throwable ex){ /*doesnt rethrow*/ }
will have to be updated. In the case of libraries that have custom execution contexts, they will need to be retrofitted to also understand this exception.
On balance, this seems like a good strategy to me. Does anybody else here think so?
In example below, if
System.exit(0)
is before the exception line, the program will be terminated normally, so the FINALLY will not execute.If the
System.exix(0)
is the last line of the try block, here we have 2 scenarios- when exception is present then finally block is executed
- when exception is not present then finally block is not executed
.
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
'Program Tip' 카테고리의 다른 글
ReferenceError를 제공하는 Javascript require () 함수 : require가 정의되지 않았습니다. (0) | 2020.11.08 |
---|---|
로그에서 잘리는 스택 추적을 어떻게 중지합니까? (0) | 2020.11.08 |
git에서 커밋 마스터 포인트를 어떻게 변경할 수 있습니까? (0) | 2020.11.08 |
Eclipse / Maven : JUnit 테스트를 실행할 때 컴파일되지 않음 (0) | 2020.11.08 |
XML 네임 스페이스는 무엇입니까? (0) | 2020.11.08 |