2012-07-06 20 views
7

Tôi hiện đang điều tra một số rò rỉ bộ nạp lớp của một ứng dụng trên Tomcat 7 (w/Oracle JDK 7). Một lớp giữ tham chiếu tĩnh tới trình nạp lớp ứng dụng web (và do đó khiến trình nạp lớp không được giải phóng khi triển khai/khởi động lại) là javax.xml.bind.DatatypeConverter, nằm trong trình nạp lớp hệ thống và giữ tham chiếu tĩnh qua trường theConverter của nó tới com.sun.xml.bind.DatatypeConverterImpl từ gói jaxb-impl của Sun.javax.xml.bind.DatatypeTrình nạp lớp bị rò rỉ trình chuyển đổi?

Có ai từng quan sát vấn đề này trước đây không? Bất kỳ đề xuất (ngoại trừ việc sử dụng phản ánh để null trường tĩnh khi tắt ứng dụng)?

+3

Thêm chi tiết về sự cố được đưa ra trong tập hợp các bài đăng trên blog này: http://java.jiderhamn.se/category/classloader-leaks/ (tìm kiếm 'jaxb' trong văn bản để biết mô tả về vấn đề mà bạn ' tái mô tả). – Guus

Trả lời

12

Khi nó bật ra, một trong những phụ thuộc của tôi (com.sun.jersey:jersey-json) được kéo vào com.sun.xml.bind:jaxb-impl, chịu trách nhiệm về trình nạp lớp Hệ thống -> Trình nạp lớp ứng dụng. Loại trừ sự phụ thuộc đó đã giải quyết được vấn đề (như JDK 7 đi kèm với việc thực hiện JAXB hợp lý, sẽ được tham chiếu trong Hệ thống CL, điều này là tốt).

0

Tomcat 8 vấn đề cảnh báo trên ứng dụng web tiếp theo triển khai lại quá trình phát triển:

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. 

tôi làm cho đống đổ trong vòng VisualVM và mở nó.

VisualVM tìm ứng dụng web bị phá hủy bộ nạp lớp trong tab OQL bởi truy vấn:

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

Thăm chỉ liên kết đến đối tượng trong "instalce" tab cho phép gọi "Tìm gốc GC gần nhất" trong "tài liệu tham khảo phần" và sao chép đại diện văn bản vào clipboard ::

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 là từ Java SE và rằng lớp được nạp bởi hệ thống classloader (và do đó đánh dấu (sticky class)). Nhưng trỏ đến lớp được tải bởi trình nạp lớp ứng dụng web.

Googling về com.sun.xml.bind.DatatypeConverterImpl dẫn đến bài đăng SO này.

giải pháp kiện kèm nói rằng việc thực hiện com.sun.jersey:jersey-json gói yêu cầu JAXB API từ com.sun.xml.bind:jaxb-impl gói ::

$ 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 

Bởi vì Java 7 đi kèm với thực hiện JAXB riêng (JAXB RI bởi thực tế), chúng tôi không cần com.sun.xml.bind:jaxb-impl gói. Thêm loại trừ tương ứng phần của 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> 

Để đạt kết quả nhanh hơn trong thử nghiệm tôi giảm bộ nhớ Tomcat ::

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

Redeploing/sử dụng ứng dụng 10 lần cho không cho ::

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

Dưới redeploys "Visual GC" plug-in hiển thị làm sạch PermGen.

Chạy với thiết lập phát triển trước yêu cầu một cái gì đó ::

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

để tồn tại 4-5 redeploys. OQL truy vấn cho lớn hơn PermGen cung cấp cho một số Tomcat của WebappClassLoader nhưng kiểm tra trường hợp cho thấy rằng không có đường dẫn đến GC và chúng được làm sạch khi PermGen trở thành đầy đủ.

Các vấn đề liên quan