mm Home

java - try with resources 본문

카테고리 없음

java - try with resources

jess_m 2017. 11. 10. 16:04

java의 try-with-resources 문법을 보다가 주변에서 close() 처리할 때 예외가 발생한다던지, catch 한곳에서 예외가 발생하면 어떻게 되느냐는 질문을 받았다. 생각해보지 않아서 대답을 못했다. 그래서 찾아봤다.



먼저 try-with-resources 를 알아보면,

AutoCloseable 인터페이스를 구현한 객체를 try() 안에 선언해놓으면 자동으로 close() 메소드를 호출해서 자원해제할 수 있도록 도와주는 기능이다. Java 7 에서 추가된 기능이며, 아래와 같이 try 문 안에 close() 처리할 객체를 생성해두면 자동으로 자원이 해제된다. 물론 다중 자원 해제도 가능하다.


try(ByteInputStream a = new ByteInputStream();
    ByteInputStream b = new ByteInputStream()) {
    //code
} catch(Exception e) {       //optional
} finally {                  //optional
}



그래, 자동으로 close() 해주는 것은 알겠다. 

그럼 어느 시점에 close 처리를 해주는 것인지, 사용자의 코드 블록에서 에러가 발생했다면, 또 close() 메소드에서 예외가 발생한다면 어떻게 되는 것인가??

try-with-resources 를 translation 해보면 쉽게 알 수 있다.


try(ByteInputStream b = new ByteInputStream()) {
    //code
} catch(Exception e) {       //optional
} finally {                  //optional
}
  
//위의 코드를 translation 하면 아래와 같다.
//개인적으로 좀 간략하게 표현한 것. 더 구체적으로 보려면 java spec을 참고할 것.
  
try {
    final ByteInputStream resource = new ByteInputStream();
    Throwable #primaryExc = null;   //try-with-resources 구문에서 자동으로 생성. Exception 처리용
  
    try {
        //code
    } catch(Throwable #t) {
        #primaryExc = #t;
        throw #t;
    } finally {
        if(resource != null) {
            if(#primaryExc != null) {   //사용자가 지정한 코드(Block)이 실행하다 예외가 발생했다면 자원을 close처리 하고, 예외를 정보를 더함.
                try{
                    resource.close();
                } catch(Throwable #suppressedExc) {
                    //실제 코드를 사용하며 발생된 Exception이 개발자 입장에서 주(primary)예외임(#primaryExc). 
                    //따라서 close()를 발생시키다 발생된 예외는 sub Exception임(#suppresedExc). 주 예외에 sub 예외를 더함.
                    #primaryExc.addSuppressed(#suppresedExc); 
                }
            } else {    //발생된 예외가 없다면, 자원을 close 처리함.
                resource.close();
            }
        }
    }
  
} catch(Exception e) {       //optional
} finally {                  //optional
}
  



코드를 보면 따로 설명이 필요없겠지만 간략히 정리하자면

- 선언된 객체를 생성

- try 문의 코드 블록을 실행

- 코드 블록에서 에러가 발생했다면 해당 예외를 throw

- 그리고 객체의 자원 해제. close() 메소드 호출

- close() 에서 에러가 발생했든지, 코드 블록에서 에러가 발생했든지, catch() 구문에서 잡힌다.

- finally 가 실행된다.



결론적으로 앞에 했던 질문을 되짚어보면,

자원 해제를 위한 close() 메소드에서 예외가 발생할 수 있다면 catch() 나 finally 에서 예외처리를 해주어야 한다는 것이다.





그리고 이 기능을 Java 9에서는 더 간결하게 사용할 수 있다.

기존에는 try() 문안에 반드시 객체를 생성해야 했는데, 객체 생성문이 없이, 생성된 객체만 집어넣어도 가능하다.


//java 9 미만
try (ByteInputStream b = new ByteInputStream()) {
} catch (Exception e) {
}
  
//java 9 
try (a;
     b) {        //이전과 동일하게 다수의 자원 선언 가능.
} catch (Exception e) {
 
}

 


Comments