우리는 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
위의 모든 것은 클래스 로더 내의 순환 참조이므로 가비지 수집을 트리거해야합니다. 왜 그런지 모르겠습니다. 누구든지 순환 참조가 있더라도 오래된 클래스 로더가 여전히 가비지 수집되지 않는 이유를 알고 있습니까?
어떤 JVM을 사용합니까 (정확한 버전)? 클래스 로딩에 영향을 줄 수있는 JVM 옵션을 사용하고 있습니까? Sun 자체 구현에서 어떤 것을 사용합니까? 응용 프로그램이 바이트 코드를 조작합니까? ... 클래스 로딩에 영향을 줄 수있는 환경은 무엇입니까? – cafebabe
주요 질문과 관련이 없지만 최신 배포를 지원하는 자체 프레임 워크 대신 OSGi와 같은 것을 고려 했습니까? – SteveD
@bfoo 테스트에서 Java 6을 사용하고 있습니다. JVM 옵션이 없습니다.우리는 가장 단순한 경우에 Sun의 impl을 사용하지 않습니다. 바이트 코드 조작이 없습니다. – onejigtwojig