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 đủ.
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