開発中の後続のWebアプリケーションの再デプロイに関するTomcat8の問題の警告:
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 [com.sun.xml.bind.v2.ClassFactory$1@79eb7926])
and a value of type [java.util.WeakHashMap]
(value [{class javax.xml.bind.annotation.W3CDomHandler=java.lang.ref.WeakReference@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タブで破壊されたWebアプリケーションクラスローダーを検索します。
select x from org.apache.catalina.loader.WebappClassLoader x where x.state.name.toString() == "DESTROYED"
[インストール]タブでオブジェクトへのポイントリンクにアクセスすると、[参照セクション]で[最も近い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
Java SEからのものであり、そのクラスはシステムクラスローダーによってロードされます(したがって、マークされます(sticky class)
)。ただし、Webアプリケーションのクラスローダーによってロードされたクラスをポイントします。
グーグルで検索com.sun.xml.bind.DatatypeConverterImpl
すると、このSO投稿につながります。
提供されたソリューションは、パッケージがcom.sun.jersey:jersey-json
パッケージからJAXBAPI実装を要求すると言い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
Java 7には独自のJAXB実装(実際にはJAXB RIcom.sun.xml.bind:jaxb-impl
)が付属しているため、
パッケージは必要ありません。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>
テストでより早く結果に到達するために、Tomcatメモリを減らします::
JAVA_OPTS="-Djava.awt.headless=true -Xmx212m -XX:+UseConcMarkSweepGC -XX:MaxPermSize=66m"
アプリケーションを10回再展開/使用すると、次の場合は何も得られません。
select x from org.apache.catalina.loader.WebappClassLoader x where x.state.name.toString() == "DESTROYED"
再デプロイの下で、「VisualGC」プラグインにPermGenのクリーンアップが表示されます。
以前の開発セットアップで実行するには、次のものが必要です。
JAVA_OPTS="-Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC -XX:MaxPermSize=256m"
4〜5回の再デプロイを生き残るために。より大きなPermGenに対するOQLクエリは、いくつかのTomcatを提供WebappClassLoader
しますが、インスタンスを調べると、GCへのパスがなく、PermGenがいっぱいになるとクリーンアップされることが示されました。