今日はPermGen OutOfMemory
エラーが発生します。コンテナ環境でLogbackを正常に停止する
this - value: org.apache.catalina.loader.WebappClassLoader #4
<- contextClassLoader (thread object) - class: java.lang.Thread, value: org.apache.catalina.loader.WebappClassLoader #4
ある:このスレッドのためのヒープ・ダンプから
java.lang.Thread#11 - logback-1
スレッドダンプ:
"logback-1" daemon prio=5 tid=34 WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)
Local Variable: java.util.concurrent.SynchronousQueue$TransferStack$SNode#1
Local Variable: java.util.concurrent.SynchronousQueue$TransferStack#6
at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:925)
Local Variable: java.util.concurrent.SynchronousQueue#6
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
Local Variable: java.util.concurrent.ThreadPoolExecutor#34
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
Local Variable: java.util.concurrent.ThreadPoolExecutor$Worker#11
at java.lang.Thread.run(Thread.java:745)
分析がWebappClassLoader
ためのGCルートはLogbackスレッドである最も近いことを示し
Tomcat 8をホットリデプロイ機能付きで使用していますE reloadable="true"
とはPreResources
経由CLASSPATH
を外部化:scan="true"
と
<Context docBase="/home/user/devel/app/src/main/webapp"
reloadable="true">
<Resources>
<!-- To override application.properties and logback.xml -->
<PreResources className="org.apache.catalina.webresources.DirResourceSet"
base="/home/user/devel/app/.config"
internalPath="/"
webAppMount="/WEB-INF/classes" />
</Resources>
</Context>
とlogback.xml
:
<configuration debug="false" scan="true" scanPeriod="5 seconds">
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
...
をTomcatの8 /home/user/devel/app/.config/logback.xml
に変更を保存した後は、(私がわからないどのようなFS上の変更を監視するために使用するAPI)の通知を受け取りますアプリケーションの再デプロイが開始されました。それはPermGen OutOfMemory
の前に起こります。
コンテナ環境でLogbackを正常に停止するにはどうすればよいですか?
"logback-1"
スレッドを停止する方法はありますか?
私はいくつかの関連する説明を見つけましたが、その情報をどのように処理するかを理解することはできません。
- http://logback.10977.n7.nabble.com/How-to-stop-all-appenders-td3023.html
- Do I need to flush events when shutting down using logback?
- Correct way to stop custom logback async appender
- Stopping Logback System for Clean Shutdown
UPDATE私はvisualvm
のヒープダンプで遊んでいます。悪いlogback-1
スレッドから参照ジャンプのレベルの下で:
lvl1 = flatten(filter(referees(heap.findObject(0xf4c77610)), "!/WebappClassLoader/(classof(it).name)"))
lvl2 = flatten(map(lvl1, "referees(it)"))
lvl3 = flatten(map(lvl2, "referees(it)"))
それは私がfound changelog entryExecutorServiceUtil
ためLogback源にgrepをすることにより
ch.qos.logback.core.util.ExecutorServiceUtil$1
を参照してください。
CHで開かれたすべてのスレッド。 qos.logback.core.util.ExecutorServiceUtil#THREAD_FACTORYは現在 デーモンであり、のシャットダウン時にアプリケーションがハングする問題を修正しましたLoggerContext#stop()が呼び出されていません(LOGBACK-929)。 デーモンスレッドがJVMによって突然終了することがあります。 は、FileAppender によって書き込まれた破損したファイルなどの望ましくない結果を引き起こします。アプリケーション は、LoggerContext#stop()(シャットダウンフックなど)を 正常終了アペンダに呼び出すことを強く推奨します。
コンテナ環境では、デーモンスレッドが危険でメモリリークにつながることは間違いありませんか?
おかげで、これは同様に私のWebappClassLoaderリークを修正しました! – whitestryder