簡體   English   中英

Sun JVM承諾的虛擬內存高消耗

[英]Sun JVM Committed Virtual Memory High Consumption

我們有運行以下設置的生產Tomcat(6.0.18)服務器:

-server -Xms7000M -Xmx7000M -Xss128k -XX:+UseFastAccessorMethods 
-XX:+HeapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote.port=7009 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false -verbose:gc -XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps 
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=/opt/apache-tomcat-6.0.18/conf/logging.properties 
-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n 
-Djava.endorsed.dirs=/opt/apache-tomcat-6.0.18/endorsed 
-classpath :/opt/apache-tomcat-6.0.18/bin/bootstrap.jar

java version "1.6.0_12"
Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
Java HotSpot(TM) 64-Bit Server VM (build 11.2-b01, mixed mode)

經過一段時間的工作,我們(通過JConsole)獲得了以下內存消耗:

Current heap size: 3 034 233 kbytes
Maximum heap size: 6 504 832 kbytes
Committed memory:  6 504 832 kbytes
Pending finalization: 0 objects
Garbage collector: Name = 'PS MarkSweep', Collections = 128, Total time spent = 16 minutes
Garbage collector: Name = 'PS Scavenge', Collections = 1 791, Total time spent = 17 minutes

Operating System: Linux 2.6.26-2-amd64
Architecture: amd64
Number of processors: 2

Committed virtual memory: 9 148 856 kbytes
Total physical memory:  8 199 684 kbytes
Free physical memory:     48 060 kbytes
Total swap space: 19 800 072 kbytes
Free swap space: 15 910 212 kbytes

問題是為什么我們有很多已提交的虛擬內存? 請注意,最大堆大小為〜7Gb(由於Xmx = 7G,這是預期的)。

頂部顯示以下內容:

31413 root  18  -2 8970m 7.1g  39m S   90 90.3 351:17.87 java

JVM為什么需要額外的2Gb! 虛擬內存? 我可以像在JRockit http://blogs.oracle.com/jrockit/2009/02/why_is_my_jvm_process_larger_t.html中一樣獲得非堆內存分配嗎?

編輯1:燙發是36M。

-Xms7000M -Xmx7000M

我對JVM說的是“將7gb作為初始堆大小分配,最大為7gb”。

因此,對於OS,該進程始終為7gb,這是JVM通過Xms標志要求的。 它實際上在JVM內部使用的是報告為幾百mb的堆大小。 通常,在防止由於過多垃圾收集而導致的速度降低時,請設置較高的Xms。 當JVM達到使用中的JVM百分比時,它將進行快速垃圾回收。 如果這樣做無法釋放內存,則會嘗試進行詳細的收集。 最后,如果失敗,並且尚未達到Xmx定義的最大內存,則會向操作系統請求更多內存。 所有這一切都需要時間,並且可以在生產服務器上真正注意到-預先執行此操作可以避免這種情況的發生。

我對jconsole不熟悉,但是您確定JVM使用的是額外的2Gb嗎? 在我看來,是因為操作系統或其他進程使總容量達到9Gb。

此外,對於使用比-Xmx參數更大的虛擬內存的JVM的常見解釋是,您具有內存映射文件(MappedByteBuffer)或使用使用MappedByteBuffer的庫。

您可能想要嘗試將JConsole連接到JVM並查看內存分配...也許您的Perm空間占用了這額外的2GB ...堆只是您的VM需要保持活動狀態的一部分...

似乎此問題是由JVM的大量頁面錯誤引起的。 當Sun的JVM遇到很多頁面錯誤時,它很可能開始分配額外的虛擬內存(仍然不知道為什么),這可能反過來進一步增加IO壓力,依此類推。 結果,我們的虛擬內存消耗很高,並且在完全GC上會定期掛起(最多30分鍾)。

三件事幫助我們在生產中獲得了穩定的工作:

  1. Linux內核交換趨勢的降低(有關詳細信息,請參見此處,Linux內核參數vm.swappiness是什么?很有幫助 我們在所有運行大量后台JVM任務的Linux服務器上均具有vm.swappiness=20

  2. 減小最大堆大小值(-Xmx),以防止對OS本身施加過多壓力。 現在,我們在12GB的計算機上擁有9GB的價值。

  3. 最后也是非常重要的-代碼分析和內存分配瓶頸優化,以盡可能消除分配突發。

就這樣。 現在服務器運行良好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM