Dziś pojawia się błąd PermGen OutOfMemory
. PokazaneWyczerpany zatrzymaj logback w środowisku kontenera
Analiza że Najbliższe GC głównej do WebappClassLoader
jest Logback gwint:
this - value: org.apache.catalina.loader.WebappClassLoader #4
<- contextClassLoader (thread object) - class: java.lang.Thread, value: org.apache.catalina.loader.WebappClassLoader #4
który jest: zrzutu
java.lang.Thread#11 - logback-1
gwintu z hałdy ładunkową do tego wątku:
"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)
Używam Tomcat 8 z hot feepem redeploy e reloadable="true"
i externalized CLASSPATH
poprzez PreResources
:
<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>
i logback.xml
z scan="true"
:
<configuration debug="false" scan="true" scanPeriod="5 seconds">
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
...
Po zapisaniu zmian w /home/user/devel/app/.config/logback.xml
Tomcat 8 otrzymywać powiadomienia (nie jestem pewien, co API wykorzystywane do monitorowania zmian na FS) rozpoczęto ponowne wdrażanie aplikacji. Tak dzieje się przed PermGen OutOfMemory
.
Jak mogę z gracją zatrzymać logback w środowisku kontenerowym?
Jak zatrzymać wątek "logback-1"
?
znalazłem kilka powiązanych dyskusji, ale nie mogę zrozumieć, co zrobić z tą informacją:
- 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 Gram z zrzutem sterty w visualvm
. Pod poziomem skoku referencyjnym od złej logback-1
wątku:
lvl1 = flatten(filter(referees(heap.findObject(0xf4c77610)), "!/WebappClassLoader/(classof(it).name)"))
lvl2 = flatten(map(lvl1, "referees(it)"))
lvl3 = flatten(map(lvl2, "referees(it)"))
odnosić się do
ch.qos.logback.core.util.ExecutorServiceUtil$1
Przez grepping w źródłach Logback dla ExecutorServiceUtil
I found changelog entry:
wszystkie wątki otwierane przez ch. qos.logback.core.util.ExecutorServiceUtil # THREAD_FACTORY to teraz demony, które naprawiają aplikację zawieszoną przy wyłączaniu, gdy LoggerContext # stop() nie jest wywoływany (LOGBACK-929). Zauważ, że wątki daemon zostały nagle przerwane przez maszynę JVM, co może spowodować, że niepożądane wyniki, takie jak uszkodzone pliki napisane przez FileAppender, mogą spowodować niepowodzenie. Nadal wysoce zalecane jest dla aplikacji wywoływanie LoggerContext # stop() (np. W haku wyłączania) na z gracją zamykającymi aplikatory.
Czy to prawda, że wątki demona w środowisku kontenerowym są niebezpieczne i prowadzą do przecieków pamięci?
Dzięki to naprawić mój WebappClassLoader przeciek, jak dobrze! – whitestryder