2010-02-26 3 views
38

우리는 Java 애플리케이션 "컨테이너"에 여러 하위 애플리케이션을로드하기 위해 여러 하위 클래스 로더를 생성하여 최신 배포를 프로토 타입 화합니다. 특정 클래스 로더의 클래스 경로가 변경된 경우 (예 : jar가 추가, 삭제, 업데이트 된 경우) 이전 클래스 로더는 버려지고 (참조되지 않음) 새로운 jarpath 클래스 경로에 대한 새로운 클래스 로더가 생성됩니다.자바 클래스 로더는 언제 어떻게 가비지 수집 대상으로 표시됩니까?

핫 배포를 트리거하는 클래스 경로를 업데이트 한 후 힙 덤프를 수행했습니다. 힙 덤프 (Memory Analyzer 사용)는 이전 클래스 로더가 가비지 수집되지 않았 음을 나타냅니다. 부모 클래스 로더의 특정 클래스가 이전 클래스 로더를 캐싱하고있었습니다. 다음과 같은 것들이 이러한 캐시를 취소하기 위해 호출되었다 :

java.lang.ResourceBundle.clearCache(classLoader); 
org.apache.commons.logging.LogFactory.release(classLoader); 
java.beans.Introspector.flushCaches(); 

는 심지어 위의 캐시를 삭제 한 후, 기존의 클래스 로더는 여전히 쓰레기는 수집되지 않았다. 클래스 로더에 나머지 참조는 다음과 같다 : 클래스 로더에 의해로드

  • 클래스를
  • java.lang.Package의 클래스 로더 자체에 의해 생성 된 클래스 로더 자체
  • 만든
  • java.lang.ProtectionDomain

위의 모든 것은 클래스 로더 내의 순환 참조이므로 가비지 수집을 트리거해야합니다. 왜 그런지 모르겠습니다. 누구든지 순환 참조가 있더라도 오래된 클래스 로더가 여전히 가비지 수집되지 않는 이유를 알고 있습니까?

+0

어떤 JVM을 사용합니까 (정확한 버전)? 클래스 로딩에 영향을 줄 수있는 JVM 옵션을 사용하고 있습니까? Sun 자체 구현에서 어떤 것을 사용합니까? 응용 프로그램이 바이트 코드를 조작합니까? ... 클래스 로딩에 영향을 줄 수있는 환경은 무엇입니까? – cafebabe

+1

주요 질문과 관련이 없지만 최신 배포를 지원하는 자체 프레임 워크 대신 OSGi와 같은 것을 고려 했습니까? – SteveD

+0

@bfoo 테스트에서 Java 6을 사용하고 있습니다. JVM 옵션이 없습니다.우리는 가장 단순한 경우에 Sun의 impl을 사용하지 않습니다. 바이트 코드 조작이 없습니다. – onejigtwojig

답변

15

언제나 Classloader 언로드에 문제가 있다고 들었습니다. 객체 인스턴스에 대한 참조가없고 클래스 언로드가 필요하지 않을 때 가비지 수집 된 것은 theoretically이지만 실제로는 더 문제가되는 것처럼 보입니다. 미묘한 참조가 누출되어 Classloader이 회수되지 않을 수 있습니다. 응용 프로그램 서버에서 많은 재배포주기 후, 때로는 OutOfMemoryError: PermGen space이 있습니다.

모두 내가 수집 한 것을 막는 불쾌한 어딘가가 있다고 생각합니다. 아마도 메모리 분석기가 링크를 올바르게 따르지 않았을 수 있습니다. 이 기사에 설명 된대로 모든 일이 일어날 수있는 것 같다 : 또한

, 당신이 일을 정확히 알고하지 않습니다,하지만 당신은 기다릴 수 있다면 JDK 7에서는 AnonymousClassLoader을 볼 수 있습니다. 이 게시물에 설명 된대로 그들은 더 나은 동적 언어를 지원하기 위해 소개합니다 :

내가 당신을 도움이되기를 바랍니다.

+0

하나의 하위 응용 프로그램은 매우 간단합니다. 사용하는 타사 라이브러리는 log4j뿐입니다. 다른 건 없어. 나머지는 기본 JDK API입니다. 또한 캐시를 유지하는 ResourceBundle 클래스를 사용합니다. clearCache()를 호출 한 후에는 해당 참조가 사라졌지만 여전히 가비지 수집을하지 않습니다. 하지만 대답 주셔서 감사합니다 :) – onejigtwojig

+0

아, 그런데, 좋은 링크! – onejigtwojig

+0

필자는 가장 단순한 하위 응용 프로그램 (한 클래스로 말하기)을 시도한 다음 클래스와 종속성을 더 추가하여 클래스 로더의 GC를 어느 시점에서 멈추는 지 확인할 수 있습니다. 하지만 시간이 많이 걸릴 수 있습니다. BTW, Frank Kievet는 XA 트랜잭션에 대한 흥미로운 게시물을 작성했습니다. – ewernli