2009-12-04 4 views
0

File Outputstream에서 압축, 암호화 및 체크섬을 수행하는 코드가 있습니다. 다른 개체와 "OS"변수를 내가 압축 등의 암호화에 대한 "OS"개체를 포장하고 여기에서 볼 수 있으며, 다음-할당 다시 같이 코드 -여러 출력 스트림 객체를 래핑 할 때 Java Outputstream 동작

private void start() { 
    OutputStream os = null; 
    try { 
     os = new FileOutputStream("/some/file"); 
     os = wrapAllRequiredTransforms(os); 

     //Write to os 
    } finally { 
     os.close(); 
    } 
} 

private wrapAllRequiredTransforms(OutputStream os) { 
    if(checkSumRequired) { 
     os = wrapOStreamWithCheckSum(os); 
    } 

    if(encryptionRequired) { 
     os = wrapOStreamWithCipher(os); 
    } 

    if(compressRequired) { 
     os = wrapOStreamWithCompress(os); 
    } 
} 

private OutputStream wrapOStreamWithCheckSum(OutputStream os) throws Exception { 
    os = new DigestOutputStream(os, MessageDigest.getInstance("MD5")); 
    return os; 
} 

private OutputStream wrapOStreamWithCipher(OutputStream os) throws Exception { 
    SecretKeySpec secretKeySpec = new SecretKeySpec(//SomeKey, encryptionAlgorithm); 
    Cipher cipher = Cipher.getInstance(encryptionAlgorithm); 
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); 
    return new CipherOutputStream(os, cipher); 
} 

private OutputStream wrapOStreamWithCompress(OutputStream os) throws Exception { 
    return new GZIPOutputStream(os); 
} 

입니다 다음 (새 사용하여 작성) wrapOStreamWithCheckSum, wrapOStreamWithCipher 및 wrapOStreamWithCompress 메서드 내부에 있습니다. 나는 이것이 메모리 누수로 이어질 지 궁금했다. 이전에 생성 된 "os"객체는 실제로 어떻게됩니까? 다시 말하면, "new"를 사용하여 생성 된 4 개의 객체가 있지만 동일한 "os"변수에 다시 할당됩니다. 나는 새로운 객체 생성/기능 자체가 오래된 객체에 내부적으로 의존하기 때문에 이해하기가 어렵다.

감사합니다,
-Keshav

+0

(예 : try/finally가 손상되었습니다. 파일이 발견되지 않으면 어떻게됩니까?) (acquire(); try {use();} finally {release();}'. :'final OutputStream rawOut = new FileOutputStream ("/ some/file /"); 시도 {final OutputStream out = 줄 바꿈 (rawOut); ...} 마지막 {rawOut.close();}'. –

+0

감사합니다. Tom! 네, 맞습니다. 오류 조건은 여기에서 처리되지 않습니다. (위의 코드는 프로그램에 복사 할 때 컴파일되지 않습니다.) 위의 코드 단편은 내가 이해하려고하는 문제 만 설명하려고 시도합니다. :) – Keshav

답변

2

이것은 Java의 표준 사례로서 안전합니다.

새로운 개체는 전달 된 개체에 대한 참조를 내부적으로 유지합니다.이 프로세스를 "래핑"또는 "위임"이라고합니다. 마지막 os을 닫으면 래핑 된 인스턴스에 메서드 호출이 전달됩니다.

이렇게하면 한 통화로 모두 닫히고 가장 바깥쪽에있는 os이 모두 해제됩니다.

0

당신 ++ 달리 C에서 메모리 누수를 만들 것입니다 기존의 객체를 자유롭게하지 걱정할 필요가 없습니다 자바, 자동 가비지 수집 메커니즘이 있습니다. 기본적으로 변수 os을 사용하여 더 이상 가리 키지 않는 객체에 매달린 참조가 없는지 확인하면됩니다.

3

개체를 스택을 통해 참조 할 수 있고 더 이상 메모리에 저장하지 않으려는 경우에만 메모리 누수가 발생합니다.

예는 다음과 같이 될 것이다 :

public class Main 
{ 
    private static CommandLineArgumentParser parser; 

    public static void main(final String[] argv) 
    { 
     parser = new CommandLineArgumentParser(argv); 
     ... use the parser 
     ... never use the parser again .... 
     ... do a bunch of work ... 
    } 
} 

파서는 더 이상 사용되지하지만 기술적으로, 당신은 더 이상 사용하고자하는 메모리 누수 (메모리 말하기,하지만 아직 할 수 있도록 여전히 연결할 수있다 가비지 컬렉터에 의해 재생 될 수 있음).

더 이상 사용하지 않으려면 null로 설정하거나 다시 할당하면됩니다. 그러면 메모리를 수집 할 수 있습니다.

래핑의 경우 "루트"개체가 사라지고 다른 라이브 참조가없는 한 모든 래핑 개체가 가비지 수집 대상이됩니다. 일단 시작 meoth가 수집 된 모든 객체를 반환하면 수집 할 수 있어야합니다.

2

출력 스트림에 대한 모든 참조는 로컬 변수에만 해당됩니다. 따라서 start()가 종료 된 후에는 남아있는 스트림에 대한 참조가 더 이상 존재하지 않으며 'Big GC'가 정리됩니다.

실제로 eclipse SDK와 실제 Java (6+)를 갖고 싶으면 os.close() 행에 중단 점을 추가하고 예상치 못한 일부 객체가 참조를 보유하고 있는지 검사 할 수 있습니다 당신의 시내.

관련 문제