2013-08-22 7 views
0

이 질문은 이전에 질문되었습니다. 그러나 문제는 좀 더 복잡해 보입니다. 나는 이것과 관련된 이전 질문의 모든 해결책을 사용했다.Freeing Java File Handles , Java keeps file locks no matter whatJava 파일 핸들이 닫히지 않습니다

package me.test; 

import java.io.File; 
import java.util.logging.FileHandler; 
import java.util.logging.Formatter; 
import java.util.logging.Level; 
import java.util.logging.LogRecord; 
import java.util.logging.Logger; 

public class Test { 
    Logger log = Logger.getAnonymousLogger(); 
    FileHandler handle; 

    final static String newline = System.lineSeparator(); 
    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     Test t = new Test(); 
     t.run(); 
    } 
    public void run() 
    { 
     for (int i = 0; i < 6; i++) { 
      testLogs(); 
      change(); 
     } 
     testLogs(); 
     if (handle != null) 
     { 
      handle.close(); 
      log.removeHandler(handle); 
     } 
    } 
    public static FileHandler craftFileHandler(File file, boolean append) 
    { 
     if (file == null) 
      return null; 
     FileHandler fh = null; 
     try { 
      fh = new FileHandler(file.getPath(), append); 
      fh.setFormatter(new Formatter() { 

       @Override 
       public String format(LogRecord record) { 
        return "[test] " + "[" + record.getLevel().toString() + "]" + String.format(record.getMessage(), record.getParameters()) + newline; 
       } 
      }); 
      return new FileHandler(file.getPath(), append); 
     } catch (Exception e) { 
      if (fh != null) 
       fh.close(); 
      return null; 
     } 
    } 

    public void change() 
    { 
     if (handle != null) 
     { 
      handle.flush(); 
      handle.close(); 
      log.removeHandler(handle); 
     } 
     handle = null; 
     File f = new File("log.log"); 
     handle = craftFileHandler(f, true); 
     System.out.println(f.getAbsolutePath()); 
     if (handle != null) 
      log.addHandler(handle); 
    } 
    public void testLogs() 
    { 
     if (log == null) 
     { 
      log = Logger.getLogger("test"); 
      log.setLevel(Level.ALL); 
     } 
     log.info("This is info #1"); 
     log.warning("Warning 1"); 
     log.info("meh info again."); 
     log.severe("SEVERE HELL YA NICE TEST"); 
     log.info("You sure its good here?"); 
     log.info("Handler count " + log.getHandlers().length); 
    } 
} 

이 코드는 테스트 코드로 의미 :

는에 관한 것이다. 나는이 테스트 파일을 만들어서 내가 가진 프로젝트에서 어떻게이 문제를 해결할 수 있는지 알아낼 수있다.

이유는 설명이 너무 빨리 발생하기 때문에이 루프가있는 이유입니다. 루프를 시뮬레이션하는 가장 좋은 방법이었습니다. 내 프로젝트에는 로그 파일을 넣을 위치를 선택할 수있는 구성이 있습니다. 그러나 파일이 다시로드되는 경우 config에서 변경되지 않습니다. 파일을 잠근 상태로두고 여분의 파일을 만드는 경향이 있습니다. EVERY 새로 고침

이 작업을하고 싶습니다. 이것이 제대로 작동하기 시작하면. 그런 다음 프로젝트에서 제대로 구현할 수 있습니다.

+0

내 코드가이 지저분 해 보입니다. 나는 더 깨끗한 코드로 포스트를 업데이트 할 것이다. 동일한 문제가 발생하는지 확인하십시오. 그렇다면 나는 최선의 결과를보고 잘못된 것을 조사한 후에 그것에 대해 더 자세하게 게시하려고 노력할 것입니다. – CoasterChris

답변

1

당신은 당신이의 FileHandler 결코 생성되기 때문에 생성 된 여러 파일을 받고 그것을 닫습니다.

fh = new FileHandler(file.getPath(), append); 
... 
return new FileHandler(file.getPath(), append); 

수정 ?

return fh; 

마지막 여부를 전혀 차이가 없습니다. 이 경우 실제로 catch 블록을 닫고 싶지는 않습니다. 그렇지 않으면 아무것도 닫을 수 없기 때문입니다.

+0

거기에 사고가 있었어야합니다. 이것은 또한 코드의 문제 중 하나입니다. – CoasterChris

+0

이 한 가지 해결 방법은 코드의 모든 문제를 해결합니다. – CoasterChris

0

음, 하나의 문제는 여기에 있습니다 :

try { 
      fh = new FileHandler(file.getPath(), append); 
      fh.setFormatter(new Formatter() { 

       @Override 
       public String format(LogRecord record) { 
        return "[test] " + "[" + record.getLevel().toString() + "]" + String.format(record.getMessage(), record.getParameters()) + newline; 
       } 
      }); 
      return new FileHandler(file.getPath(), append); 
     } catch (Exception e) { 
      if (fh != null) 
       fh.close(); 
      return null; 

당신은 오류가있는 경우에만 그것을 닫는 try 문에서 파일을 닫습니다하지 않습니다. 당신이 함께 할만큼 곧 파일을 닫아야합니다 :

try { 
      fh = new FileHandler(file.getPath(), append); 
      fh.setFormatter(new Formatter() { 

       @Override 
       public String format(LogRecord record) { 
        return "[test] " + "[" + record.getLevel().toString() + "]" + String.format(record.getMessage(), record.getParameters()) + newline; 
       } 
      }); 
      //close fh 
      fh.close(); 
      return new FileHandler(file.getPath(), append); 
     } catch (Exception e) { 
      if (fh != null) 
       fh.close(); 
      return null; 
+0

코드를 다시 읽으십시오. 반환 할 fh의 새로운 FileHandler를 생성합니다. 그런 다음 원본을 사용하지 않고 닫고 새 것을 다시 만드시겠습니까? 이해가 되니? – CoasterChris

2

항상 가까운 자원을 내부 마지막 블록 -

try { 
    fh = new FileHandler(file.getPath(), append); 
    fh.setFormatter(new Formatter() { 

    @Override 
    public String format(LogRecord record) { 
     return "[test] " + "[" + record.getLevel().toString() + "]" + String.format(record.getMessage(), record.getParameters()) + newline; 
    } 
    }); 
    return new FileHandler(file.getPath(), append); 
} catch (Exception e) { 

    return null; 
    // never close in catch 

} finally { 
    // lastly close anything that may be open 
    if (fh != null){ 
     try { 
      fh.close(); 
     } catch (Exception ex){ 
      // error closing 
     } 
    } 
} 
+0

개체를 반환 할 때 어떻게 작동합니까? (본질적으로 try 문 종료) – CoasterChris

+2

@CoasterChris 그게 그 아름다움입니다. try 내부의 return 문은 finally 블록이 완료되고 반환 될 때까지 핸들러를 저장합니다. 물론 컴퓨터를 끄지 않으면 마침내 항상 실행됩니다. 같은 일이 잡으려고 간다. null를 돌려주기 전에, finally가 실행되어 null가 돌려 주어집니다. –

+0

Dutta 고맙습니다. 나는 try 블록을 시도했다. jvm은 이제 나를 혼란스럽게 만들었습니다. 그러나 긴밀한 진술은 어느 방향에서나 효과가 있었음에 틀림 없다. 코드의 다른 부분을 자세히 보았습니까? 어떻게 작동하지 않는지에 대한 아이디어가 있습니까? – CoasterChris

0

사용 후 log 메소드는 모든 핸들러를 닫습니다.

this.logger.log(Level.SEVERE, (exception.getClass().getName() + ": " + exception.getMessage()) + "\r\n" + exception.getCause() + "\r\n" + "\r\n"); 

    for (Handler handler : this.logger.getHandlers()) 
    { 
     handler.close(); 
    }