JVM 플래그 CMSClassUnloadingEnabled는 실제로 무엇을합니까?


183

나는 CMSClassUnloadingEnabled"PermGen 문제를 제거한다"( btw 가 아닌 ) 와 같은 매우 희미한 고급 정의 외에 Java VM 플래그가 실제로 수행 하는 것에 대한 정의를 찾을 수 없다 .

Sun / Oracle 사이트를 살펴 보았고 옵션 목록 조차 실제로 실제로 무엇을 말하지는 않습니다.

플래그의 이름을 기준으로 CMS 가비지 콜렉터는 기본적으로 언로드 클래스를하지 않으며이 플래그를 설정하지만 확실하지 않습니다.

답변:


219

업데이트이 답변은 Java 5-7과 관련이 있으며 Java 8에는 다음 사항이 수정되었습니다. https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace Kudos는 mt 로 이동 하십시오 . 울루

Java 5-7의 경우 :

세계에서 표준 Oracle / Sun VM보기는 다음과 같습니다. 클래스는 영원합니다. 따라서 일단로드되면 더 이상 신경 쓰지 않아도 메모리에 남아 있습니다. 순전히 "설정"클래스가 많지 않기 때문에 일반적으로 문제가되지 않습니다. 따라서 1MB를 차지하더라도 누가 신경 써야합니다.

그러나 최근에는 런타임에 클래스를 정의하는 Groovy와 같은 언어가 있습니다. 스크립트를 실행할 때마다 하나 이상의 새 클래스가 만들어지고 PermGen에 영원히 머무 릅니다. 서버를 실행하는 경우 메모리 누수가 있음을 의미합니다.

CMSClassUnloadingEnabledGC 를 활성화 하면 PermGen도 스윕하고 더 이상 사용되지 않는 클래스를 제거합니다.

[편집] 또한 활성화해야합니다 UseConcMarkSweepGC( Sam Hasler 덕분에 ). 이 답변을 참조하십시오 : https://stackoverflow.com/a/3720052/2541


17
영향을 미치 려면 stackoverflow.com/a/3720052/2541 에 따라 설정해야합니다CMSClassUnloadingEnabledUseConcMarkSweepGC
Sam Hasler

1
이것이 UseConcatSweepGC 사용 아이디어에 어떤 영향을 미치는지 확실하지 않지만 CMSClassUnloadingEnabled에서 최근에 수정 된 버그가있는 것 같습니다. 버그
Bill Rosmus 2018 년

3
@ 케빈 : 네, 물론입니다. 하단에 참조 groovy.codehaus.org/Running ". 그루비 동적으로 클래스를 생성하지만 기본 자바 VM은 PermGen를 GC하지 않습니다 당신은 자바 6 사용하는 경우 이상 추가 -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC. UseConcMarkSweepGC수 있도록하는 데 필요합니다 CMSClassUnloadingEnabled."
Aaron Digulla

1
UseConcMarkSweepGC와 CMSClassUnloadingEnabled를 함께 사용하는 방법에 대한 좋은 기사입니다. blog.redfin.com/devblog/2012/06/…
Victor

1
더 이상 1.8에 유효하지 않습니다 : blogs.oracle.com/poonam/…
mt.uulu

35

블로그 게시물에 따르면 Java JVM의 가장 완벽한 -XX 옵션 목록은 CMS 가비지 수집기에서 클래스 언로드가 활성화되어 있는지 확인합니다. 기본값은 false입니다. 라는 또 다른 옵션이 ClassUnloading있습니다 true(아마도) 다른 쓰레기 수집에 영향을 미치는 기본적으로는.

아이디어는 GC가 이전에로드 된 클래스가 더 이상 JVM의 어느 곳에서도 사용되지 않음을 감지하면 클래스 바이트 코드 및 / 또는 기본 코드를 보유하는 데 사용 된 메모리를 회수 할 수 있다는 것입니다.

CMSClassUnloadingEnabled를 설정 하면 현재 CMS 수집기를 사용중인 경우 permgen 문제에 도움이 될 수 있습니다 . 그러나 CMS를 사용하지 않거나 클래스 로더 관련 메모리 누수가 발생할 가능성이 있습니다. 후자의 경우 클래스는 GC에 사용되지 않은 것처럼 보이지 않으므로 언로드되지 않습니다.


Aaron Digulla는 "수업은 영원합니다"라고 말합니다. 순수한 Java 세계에서도 마찬가지입니다. 실제로 클래스의 수명은 클래스 로더와 연결되어 있습니다. 따라서 클래스 로더가 가비지 수집되도록 정렬 할 수 있다면 (그리고 항상 쉬운 것은 아닙니다)로드 된 클래스도 가비지 수집됩니다.

실제로, 이것은 웹 애플리케이션을 재 전개 할 때 발생합니다. (또는 최소한 permgen 스토리지 누출로 이어지는 문제점을 피할 수있는 경우에 발생합니다.)


24

이것이 유용한 예 :

-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabledWeblogic 10.3 JVM을 설정 하면 JAX-WS 구현이 모든 웹 서비스 호출에 대해 새 프록시 클래스를 작성하여 메모리 부족 오류가 발생하는 문제를 해결하는 데 도움이되었습니다.

추적하기가 쉽지 않았습니다. 다음 코드는 항상 동일한 프록시 클래스를 반환했습니다.port

final MyPortType port = 
Service.create(
        getClass().getResource("/path/to.wsdl"), 
        new QName("http://www.example.com", "MyService"))
    .getPort(
        new QName("http://www.example.com", "MyPortType"), 
        MyPortType.class);

내부적으로이 프록시는의 인스턴스에 위임되었습니다.이 인스턴스는 매번 호출 할 때마다 증가 weblogic.wsee.jaxws.spi.ClientInstance된 새 $Proxy[nnnn]클래스에 위임되었습니다 n. 플래그를 추가 할 때 n여전히 증가했지만 최소한 임시 클래스는 메모리에서 제거되었습니다.

보다 일반적으로, 이것은 자바 리플렉션 및 프록시를 많이 사용하는 경우 매우 유용 할 수 있습니다. java.lang.reflect.Proxy


실제 경험 공유를위한 +1 또한 JRuby 컴파일 프로세스로 인해 서버가 많은 수의 클래스를 생성 한 torquebox에서도이 문제가 발생했습니다.
nurettin

7
또한 노트 -XX:+CMSPermGenSweepingEnabled에 찬성되지 않습니다-XX:+CMSClassUnloadingEnabled
nurettin

3
이 문제에 대한 실질적인 해결책은 포트를 한 번 생성하여 재사용하는 것입니다. 이것이 JAX-WS가 사용되는 방식입니다. 포트는 100 % 스레드 안전합니다.
rustyx

@rustyx : 권위있는 링크로 그 주장을 뒷받침 할 수 있습니까? 난 항상 봤는데 매우 다시 사용하여 웹 서비스 프록시와 스텁의주의 ... 예를 볼 아파치 CXF 부인을 . 또는 이 질문
Lukas Eder

1
@rukavitsya : 내가 대답했듯이. 위의 논리를 호출 할 때마다 새로운 프록시가 생성되었습니다
Lukas Eder
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.