2010-04-25 4 views
1

보통 코드는 내가이 같은 일을 참조 출시 될 필요가 일부 자원을 필요로 할 때 :Java에서 자원을 안전하게 릴리스 할 수 있습니까?

InputStream in = null; 
try{ 
    in = new FileInputStream("myfile.txt"); 
    doSomethingWithStream(in); 
}finally{ 
    if(in != null){ 
     in.close(); 
    } 
} 

내가 좋아하지 않는 것은 당신이 null로 변수를 초기화해야하고 그 후 다른로 설정한다는 것입니다 값을 반환하고 finally 블록에서 null인지 확인하여 리소스가 초기화되었는지 확인합니다. 널이 아닌 경우, 공개해야합니다. 내가 nitpicking 오전 알지만,이 청소기를 할 수 있다고 생각합니다. 내 눈에

InputStream in = new FileInputStream("myfile.txt"); 
try{ 
    doSomethingWithStream(in); 
}finally{ 
    in.close(); 
} 

이 거의 안전한 이전과 같습니다

는 내가 뭘하고 싶은 것은 이것이다. 리소스 초기화에 실패하고 예외가 발생하면 try 블록 안에있을 필요가 없으므로 아무 것도 할 필요가 없습니다 (리소스를 얻지 못했기 때문에). 내가 걱정하는 유일한 방법은 작업간에 예외 또는 오류가 발생할 수있는 방법이 있다면 (Java 인증이 아님)?

심지어 간단한 예 :

Inputstream in = new FileInputStream("myfile.txt"); 
in.close(); 

스트림이 시도가-finally 블록을 방지 할 수 있음을 개방 될 수있는 방법이 있나요?

편집 : 모든 사람을 혼란 때문에

어쩌면 내가 마지막 예제를 남겨해야합니다. 이것은 초급 수준의 질문으로 생각되지 않습니다. try-finally가하는 일을 알고 있고 마지막 예제의 중간에 doSomethingWithStream이 있으면 안전하지 않다는 것을 안다. 그것이 거기에없는 이유입니다. 나는 Eyals의 대답을 받아 들였다. 정확히 내가 찾고 있던 것이기 때문이다. 두 작업 사이에 예외를 발생시키는 방법이 있는데 중간 예제는 안전하지 않습니다 (Thread.stop 사용).하지만 deprecated 호출을 사용하여 이루어 지므로 작업 내용에 상관없이 작업을 망칠 수 있습니다. 중간 예제.

+1

그런데 Apache Commons를 사용하는 경우 IOUtils.close Quietly (in)을 할 수 있습니다. 이 유틸리티 함수는'null'을 검사하고'IOException'을 억제합니다. 아마도 어쨌든 닫는 예외에 관심이 없을 것입니다. – doublep

+0

@doublep : 팁 주셔서 감사합니다. 거기에 다른 유용한 것들이 많이있는 것처럼 보입니다. – palto

+0

설명을 위해 마지막 예제에서 doSomethingWithStream은 의도적으로 생략되었습니다. – palto

답변

1

실제로 마지막 코드 샘플의 두 호출간에 예외가 발생할 수 있으며 리소스를 열린 상태로 둡니다. thread가 스트림의 작성 직후에 Thread.stop() 또는 Thread.stop (Throwable)를 사용해 다른 thread에 의해 격렬하게 정지되고있는 경우, thread는 예외 (최초의 경우 ThreadDeath)를 throw 해, 자원은 삭제되지 않습니다 의.

그러나이 방법이 사용되지 않습니다 이유는 정확히 ... Project Lombok

+0

이것이 내가 스트림을 풀어 놓는 방식을 사용하면 안되는 심각한 문제라고 생각 하나? – palto

+0

사실,하지만'try' -'finally'를 추가하면 도움이되지 않습니다. –

+0

왜 도움이되지 않습니까? 마지막 예제가 첫 번째 예제와 같이 보호된다면 ThreadDeath 오류에서도 안전하지 않습니까? – palto

2

중간 샘플은 안전합니다. 마지막 샘플은 안전하지 않습니다.

try-finally 블록은 doSomethingWithStream이 예외를 throw하더라도 스트림이 닫힌다는 것을 의미합니다. 예, 모든 예외를 catch 한 다음 그 방법으로 스트림을 닫을 수 있습니다. 예외 호출을 호출자에게 보내고 finally 블록을 통해 스트림을 닫는 것이 훨씬 간단합니다.

+2

마지막 하나는 안전하지만, 의도적으로'doSomethingWithStream (in)'을 그 사이에 넣는 것이 겠지요. 물론 그것은 안전하지 않을 것입니다. – doublep

+0

왜 마지막 것이 안전하지 않습니까? (나는 너무 느리고 doublep는 이미 대답했다.) – palto

+0

마지막 예제에서 호출 사이에 doSomethingWithStream (in)을 넣지 않았다. 나는이 질문이 "이 두 가지 작업간에 뭔가 잘못 될 수있는 것"이라고 생각합니다. – palto

0

봐. 로컬 변수에 설정할 수있는 @Cleanup 주석이 있는데, auto-generate code at compilation time을 사용하여 리소스를 정리합니다.

import lombok.Cleanup; 
import java.io.*; 

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    @Cleanup InputStream in = new FileInputStream(args[0]); 
    @Cleanup OutputStream out = new FileOutputStream(args[1]); 
    byte[] b = new byte[10000]; 
    while (true) { 
     int r = in.read(b); 
     if (r == -1) break; 
     out.write(b, 0, r); 
    } 
    } 
} 
+0

흥미 롭지 만 Eclipse와 꽤 많이 결혼 한 것 같고 Netbeans를 사용합니다. – palto

+0

솔직히 말해서 Eclipse를 잘못 처리하는 방식에 만족하지 않습니다. API를 언제든지 변경할 수있는 바이트 코드 재 작성 및 메모리 내 메소드 변경을 사용합니다. –

관련 문제