2016-02-26 101 views
2

我正在使用內嵌的Jetty服務器運行此應用程序。儘管堆大小根本沒有改變,但應用程序正在慢慢消耗更多的內存。具有碼頭內存泄漏問題的java服務器

這是啓動應用程序的命令:

的java -server -Xms1G -Xmx1G -Dfile.encoding = UTF-8

這是從與所述RAM的使用增加 enter image description here新遺蹟圖表 它開始使用1140MB和8小時後1290MB完成

這是堆的jvisualvm圖表。 enter image description here

有什麼建議嗎?

[EDIT1] 添加轉儲https://www.dropbox.com/s/1gt1i9dhjtjauf0/gameserver-20160226-2107.zip?dl=0

[EDIT2] 下面是我目前的調查

=一些注意事項如何監視內存堆 之外添加參數

-XX:NativeMemoryTracking=detail -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics 

運行命令 jcmd 3322 VM.native_memory摘要 @ see https://devcenter.heroku.com/articles/java-memory-issues

=檢查默認線程堆棧大小 java -XX:+ PrintFlagsFinal -version | grep的ThreadStackSize

的INTx ThreadStackSize = 1024
How to reclaim the memory used by a Java thread stack?

=瞭解最大存儲器 最大值存儲器= [-Xmx] + [-XX:MaxPermSize參數] + number_of_threads * [ - Xss] @ see https://plumbr.eu/blog/memory-leaks/why-does-my-java-process-consume-more-memory-than-xmx

=操作 縮小尺寸的線程堆棧。 (理論上,你可以低至64K ...)

-XX:ThreadStackSize=256 

減少GC之後堆的最小百分比以避免擴展。

-XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=10 

現在將繼續監控...

+0

您可能忘記關閉'Closeable',例如'Connection','Transaction','FileOutputStream'等。它也可能來自本地庫的使用。 –

+0

謝謝@ArnaudDenoyelle,但我相信會顯示堆使用情況圖表,堆總是低於400MB(傷心) –

+1

根據所提供的信息,根本不可能說你是否有內存泄漏。 –

回答

1

經過大量的不同類型的調查,我又重新回到了Eclipse Memory analyzer,並試圖再次...

但這次我決定信任泄漏報告是說:

通過 裝 「org.hibernate.internal.SessionFactoryImpl」 的

一個實例「sun.misc.Launcher $ AppClassLoader @ 0xc001 d4f8「佔據2.956.808 (21,05%)字節。內存在 「org.hibernate.internal.SessionFactoryImpl」的一個實例中被積累,該實例由 「sun.misc.Launcher $ AppClassLoader @ 0xc001d4f8」加載。

然後我轉移我的調查我的DAO實現,期待我忘記關閉一個或其他EntityManager調用。情況並非如此,所有這些都是在使用後用close()方法調用的。

然後,我意識到問題可能是在冬眠本身有問題的對象是一個SessionFactory的默認地將Impl,所以我改變了我的DAO實現以清除每次我創建一個實體管理器時,Hibernate的一級緩存,因爲我wasn'能夠找到一種方法來禁用它。

當天結束=結果=工作! :)記憶改變了一會兒,並在幾分鐘後回來,但不再以瘋狂的方式成長(24小時內有1000MB)。

這是我改變的代碼,希望它可以幫助別人。

public EntityManager getEntityManager(){ 
    if(emf == null){ 
     if (parameters == null) { 
      emf = Persistence.createEntityManagerFactory(persistenceUnitName); 
     } else { 
      emf = Persistence.createEntityManagerFactory(persistenceUnitName, parameters); 
     } 
    } else { 
     emf.getCache().evictAll(); 
    } 

    EntityManager em = emf.createEntityManager(); 
    return em; 
} 

的關鍵是在這裏:emf.getCache()evictAll();