2015-10-29 62 views
1

我在多個服務器上有JDK 8,並且堆大小一直增加,直到達到90%並且應用程序失敗。在這段時間內,多個GC運行,但老一代繼續增長,直到應用程序失敗。目前的解決方法是重新啓動Tomcat。我的服務器有15GB RAM,4核心CPU。我的Java設置是:Java老一代繼續增長,直到Tomcat重新啓動

-Xms12036M -Xmx12036M -Xmn800M 

對這些值有任何建議嗎?我以爲GC會照顧它,但老一代似乎沒有。我是Java新手,不確定這是否表示內存泄漏,或者GC是否沒有這樣做?

+3

我會檢查你的申請泄漏。你有沒有嘗試過使用探查器? – jgitter

回答

2

首先用JStacks/JMaps,線程轉儲和內存分析工具檢查內存泄漏。如果你的系統內存沒有任何泄漏,你必須微調垃圾收集器算法。

Java提供了不同類型的垃圾收集器。

看一看優勢&弱點的各種GC algorithms

  1. 串行收集:串行收集器是最簡單的一個,你可能不會使用的一個,因爲它的主要設計對於單線程環境。

  2. 並行/吞吐量收集器:它最大的優點是使用多線程掃描並壓縮堆。並行收集器的缺點是它會在執行次要或完整GC採集時停止應用程序線程。

  3. 的CMS收集器:該算法使用多線程(「併發」)通過堆(「標記」),選擇那些可以再循環(「掃描」)未使用的對象進行掃描。如果您要麼增加老一代(或整個堆)的大小,要麼爲收集器分配更多的後臺線程會更有效率。它使用更多的CPU來爲應用程序提供更高級別的連續吞吐量。

  4. G1收集器:在JDK 7 update 4中引入的垃圾第一收集器(G1)旨在更好地支持大於4GB的堆。 G1採集器利用多個後臺線程掃描它分成多個區域的堆,從1MB到32MB(取決於堆的大小)。使用-XX:+ UseG1GC標誌。

如果您使用G1收集器,則必須微調區域大小參數。如果15 GB是堆大小,則您的區域大小應爲(15 GB/2048)MB,大約爲7 MB。不要嘗試更多新的尺寸。您可以堅持默認設置,因爲此算法提供了默認值的最佳性能。

看一看這篇文章:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc_tuning.html

+0

非常感謝,所有人都非常感謝。 – raindrop

2

我不認爲你的參數有什麼問題。我建議在你的代碼中尋找內存泄漏。使用探查器是一個好主意,但您也可以查找泄漏模式。這裏是一個很好的集合:Creating a memory leak with Java

1

GC JVM的是對於不通過你的主程序引用的對象只是響應,(包括「參考週期」),

如果在堆許多對象不能用GC, 造成收集OOM兩個可能性:

  1. 這些對象是由你的程序邏輯需要:
    你需要添加內存資源,或者需要改變的過程您的程序 ,以避免使用大量的內存資源。

  2. 在邏輯上並不需要這些對象,而是通過自己的主程序仍然被引用, (例如:是沒有必要的對象,但並沒有從列表中刪除 ): 它在Java內存泄漏,它是一個bug,你必須在你的程序中修復它。

嘗試使用一些性能分析工具,或者跟蹤你的代碼找出是否是內存泄漏問題。

0

-Xmn800M(800MB年輕一代)似乎像一個12GB堆一個相當低的數值。考慮只是徹底殺死那個參數,只保留-Xms12036M -Xmx12036M參數。

請注意,您的老一代將繼續增長,直到完整的GC運行。你會有很多次要的GC,它們會在首個800MB上執行GC,但不會在剩下的11.2GB上執行GC。因此,請嘗試compare heap dumps using something the Eclipse Memory Analysis Tool。另外,請嘗試grab a few different heap dumps。留意尺寸單調增長的物體。

相關問題