2012-07-06 5 views
7

현재 Tomcat 7 (Oracle JDK 7 포함)에서 응용 프로그램의 일부 클래스 로더 유출을 조사 중입니다. 웹 응용 프로그램 클래스 로더에 대한 정적 참조를 유지하는 클래스 (따라서 재배포/다시 시작할 때 클래스 로더가 해제되지 않음)는 시스템 클래스 로더에있는 javax.xml.bind.DatatypeConverter이며 theConverter 필드를 통한 정적 참조는 com.sun.xml.bind.DatatypeConverterImpl Sun의 jaxb-impl 패키지에서 가져온 것입니다.클래스 로더를 누설하고있는 javax.xml.bind.DatatypeConverter?

이전에이 문제를 본 사람이 있습니까? 어떤 제안 (응용 프로그램 종료시 정적 필드를 null로 리플렉션하는 것을 제외하고)?

+3

이 문제에 대한 자세한 내용은 다음 블로그 게시물에 나와 있습니다. http://java.jiderhamn.se/category/classloader-leaks/ (텍스트 'jaxb' 다시 설명). – Guus

답변

12

내 시스템 종속성 중 하나 (com.sun.jersey:jersey-json)는 시스템 클래스 로더 -> 응용 프로그램 클래스 로더 참조를 담당하는 com.sun.xml.bind:jaxb-impl을 가져 왔습니다. 이러한 종속성을 제외하면 JDK 7은 System CL에서 참조 할 수있는 적절한 JAXB 구현을 제공하므로 문제는 해결됩니다. 이후 웹 응용 프로그램에 경고 8 문제가 개발 과정에서 재배치

0

톰캣 :

org.apache.catalina.loader.WebappClassLoaderBase checkThreadLocalMapForLeaks 

SEVERE: The web application [rsnetlombard] created a ThreadLocal with key of type 
[com.sun.xml.bind.v2.ClassFactory$1] (value [[email protected]]) 
and a value of type [java.util.WeakHashMap] 
(value [{class java[email protected]525eec52}]) 
but failed to remove it when the web application was stopped. 
Threads are going to be renewed over time to try and avoid a probable memory leak. 

나는 VisualVM과 내 힙 덤프을 엽니 다.

VisualVM과 요청에 의한 OQL 탭에서 파괴 된 웹 애플리케이션 클래스 로더를 찾을 수 :

select x from org.apache.catalina.loader.WebappClassLoader x where x.state.name.toString() == "DESTROYED" 

방문은 "instalce"탭이 호출 "참조 섹션"에서 "가장 가까운 GC 뿌리 찾기"허용에 반대하는 링크를 지적 및 복사 텍스트 표현은 클립 보드에 ::

this  - value: org.apache.catalina.loader.WebappClassLoader #3 
<- <classLoader>  - class: com.sun.xml.bind.DatatypeConverterImpl, value: org.apache.catalina.loader.WebappClassLoader #3 
    <- <class>  - class: com.sun.xml.bind.DatatypeConverterImpl, value: com.sun.xml.bind.DatatypeConverterImpl class DatatypeConverterImpl 
    <- theConverter (sticky class)  - class: javax.xml.bind.DatatypeConverter, value: com.sun.xml.bind.DatatypeConverterImpl #1 

javax.xml.bind.DatatypeConverter

자바 SE에서이고 시스템 클래스 로더 에 의해로드 된 클래스는 (그래서 (sticky class) 표시). 그러나 웹 애플리케이션 클래스 로더에 의해로드 된 클래스를 가리 키십시오.

Google 검색에 대해 com.sun.xml.bind.DatatypeConverterImpl이 게시물로 연결됩니다.

납품 솔루션은 자바 7이 자신의 JAXB 구현 (사실에 의해 JAXB RI)와 함께 제공하기 때문에 com.sun.jersey:jersey-json 패키지 요청 JAXB API를 구현 패키지 : com.sun.xml.bind:jaxb-impl에서

$ mvn dependency:tree 
... 
[INFO] +- com.sun.jersey:jersey-json:jar:1.8:compile 
[INFO] | +- org.codehaus.jettison:jettison:jar:1.1:compile 
[INFO] | | \- stax:stax-api:jar:1.0.1:compile 
[INFO] | +- com.sun.xml.bind:jaxb-impl:jar:2.2.3-1:compile 
[INFO] | | \- javax.xml.bind:jaxb-api:jar:2.2.2:compile 
[INFO] | |  \- javax.xml.stream:stax-api:jar:1.0-2:compile 
[INFO] | +- org.codehaus.jackson:jackson-core-asl:jar:1.7.1:compile 
[INFO] | +- org.codehaus.jackson:jackson-mapper-asl:jar:1.7.1:compile 
[INFO] | +- org.codehaus.jackson:jackson-jaxrs:jar:1.7.1:compile 
[INFO] | \- org.codehaus.jackson:jackson-xc:jar:1.7.1:compile 

우리는 com.sun.xml.bind:jaxb-impl 패키지를 필요로하지 않는다는 것을 말한다. 나는 응용 프로그램을 10 번 사용/톰캣 메모리 ::

JAVA_OPTS="-Djava.awt.headless=true -Xmx212m -XX:+UseConcMarkSweepGC -XX:MaxPermSize=66m" 

Redeploing을 줄일 ::

에 대한 아무 것도주지 주문 도달 결과 빠른 테스트에서 pom.xml의 일부 ::

<dependency> 
     <groupId>com.sun.jersey</groupId> 
     <artifactId>jersey-json</artifactId> 
     <version>${jersey.version}</version> 
     <exclusions> 
      <exclusion> 
       <groupId>com.sun.xml.bind</groupId> 
       <artifactId>jaxb-impl</artifactId> 
      </exclusion> 
     </exclusions> 
    </dependency> 

대응에 제외 추가

select x from org.apache.catalina.loader.WebappClassLoader x where x.state.name.toString() == "DESTROYED" 

재사용 중 "Visual GC"플러그인에 PermGen 클린업이 표시됩니다.이전 개발 설치를 실행

뭔가 ::

JAVA_OPTS="-Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC -XX:MaxPermSize=256m" 

4-5 재배포를 생존을 위해 필요합니다. 더 큰 PermGen에 대한 OQL 쿼리는 여러 Tomcat의 WebappClassLoader 을 제공하지만 GC에 대한 경로가 없다는 것을 보여주는 인스턴스를 확인하면 PermGen이 가득 채워져 이 될 때 정리됩니다.

관련 문제