OutOfMemoryError.jmap隨筆淺談

jmap(查看內存)命令

-bash-4.1# jmap --help
Usage:
    jmap [option] <pid>
        (to connect to running process)
    jmap [option] <executable <core>
        (to connect to a core file)
    jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

where <option> is one of:
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system
-bash-4.1#

在上面有一些命令的解釋,和Example.

命令中的參數解釋:

option:選項參數,不可同時使用多個選項參數

pid:java進程id,命令ps -ef | grep java獲取

executable:產生核心dump的java可執行文件

core:需要打印配置信息的核心文件

remote-hostname-or-ip:遠程調試的主機名或ip

server-id:可選的唯一id,如果相同的遠程主機上運行了多臺調試服務器,用此選項參數標識服務器

options的參數

heap : 顯示Java堆詳細信息

histo : 顯示堆中對象的統計信息

permstat :Java堆內存的永久保存區域的類加載器的統計信息

finalizerinfo : 顯示在F-Queue隊列等待Finalizer線程執行finalizer方法的對象
dump : 生成堆轉儲快照
F : 當-dump沒有響應時,強制生成dump快照

舉個例子:

-bash-4.1# jmap -heap 11187
Attaching to process ID 11187, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11

using thread-local object allocation.
Parallel GC with 2 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 492830720 (470.0MB)
   NewSize                  = 10485760 (10.0MB)
   MaxNewSize               = 164102144 (156.5MB)
   OldSize                  = 20971520 (20.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 72876032 (69.5MB)
   used     = 30822272 (29.3944091796875MB)
   free     = 42053760 (40.1055908203125MB)
   42.29411392760792% used
From Space:
   capacity = 16252928 (15.5MB)
   used     = 5137416 (4.899421691894531MB)
   free     = 11115512 (10.600578308105469MB)
   31.60917220577117% used
To Space:
   capacity = 15728640 (15.0MB)
   used     = 0 (0.0MB)
   free     = 15728640 (15.0MB)
   0.0% used
PS Old Generation
   capacity = 169869312 (162.0MB)
   used     = 112301376 (107.09893798828125MB)
   free     = 57567936 (54.90106201171875MB)
   66.11045554832175% used

42026 interned Strings occupying 4596712 bytes.

jmap -heap [PID]  ( 這裏的PID 通過 ps -ef | grep java 來查看當前正在運行的java進程來獲取PID )

打印heap的概要信息,GC使用的算法,heap的配置及使用情況,可以用此來判斷內存目前的使用情況以及垃圾回收情況

(通過上面打印發現沒有PermSize 永生代的初始大小, MaxPermSize永生代的最大大小 , 永久代在JDK8中被完全的移除了。所以永久代的參數-XX:PermSize和-XX:MaxPermSize也被移除了. 永久代移除詳情鏈接 )

jmap -finalizerinfo [PID] 

打印等待回收的對象信息

-bash-4.1# jmap -finalizerinfo 11187
Attaching to process ID 11187, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
Number of objects pending for finalization: 0 #說明當前F-QUEUE隊列中並沒有等待Fializer線程執行finalizer方法的對象。

jmap -histo [PID]

打印堆的對象統計,包括對象數、內存大小等等。

-bash-4.1# jmap -histo 11187
.........中間太多了打印看不見了
序號            實例數量         字節     類名
6599:             1             16  sun.text.normalizer.NormalizerBase$NFCMode
6600:             1             16  sun.text.normalizer.NormalizerBase$NFDMode
6601:             1             16  sun.text.normalizer.NormalizerBase$NFKCMode
6602:             1             16  sun.text.normalizer.NormalizerBase$NFKDMode
6603:             1             16  sun.text.normalizer.NormalizerImpl
6604:             1             16  sun.text.normalizer.NormalizerImpl$AuxTrieImpl
6605:             1             16  sun.text.normalizer.NormalizerImpl$FCDTrieImpl
6606:             1             16  sun.text.normalizer.NormalizerImpl$NormTrieImpl
6607:             1             16  sun.util.calendar.Gregorian
6608:             1             16  sun.util.locale.InternalLocaleBuilder$CaseInsensitiveChar
6609:             1             16  sun.util.locale.provider.AuxLocaleProviderAdapter$NullProvider
6610:             1             16  sun.util.locale.provider.CalendarDataUtility$CalendarWeekParameterGetter
6611:             1             16  sun.util.locale.provider.SPILocaleProviderAdapter
6612:             1             16  sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter
6613:             1             16  sun.util.resources.LocaleData
6614:             1             16  sun.util.resources.LocaleData$LocaleDataResourceBundleControl
Total       2362889      122539696
-bash-4.1#

注意* jmap -histo:live [pid] 這個命令執行,JVM會先觸發gc,然後再統計信息 . 在正式環境慎用.

擴展 : 使用 jmap -histo:live 11187 | grep  normalizer > junbao_HeapDump.txt  (是打印出存活的 過濾出帶有 normalizer字樣的 堆信息 保存到當前所在層級的 junbao_HeapDump.txt文件中.)

 

jmap -permstat [PID]

打印Java堆內存的永久區的類加載器的智能統計信息。對於每個類加載器而言,它的名稱、活躍度、地址、父類加載器、它所加載的類的數量和大小都會被打印。此外,包含的字符串數量和大小也會被打印。

粘貼的事例.非同一臺服務.共參考
[root@localhost jdk1.7.0_79]# jmap -permstat 24971
Attaching to process ID 24971, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.79-b02
finding class loader instances ..done.
computing per loader stat ..done.
please wait.. computing liveness....................................................liveness analysis may be inaccurate ...
class_loader    classes bytes   parent_loader   alive?  type
 
<bootstrap>   3034    18149440      null      live    <internal>
0x000000070a88fbb8  1   3048      null      dead    sun/reflect/DelegatingClassLoader@0x0000000703c50b58
0x000000070a914860  1   3064    0x0000000709035198  dead    sun/reflect/DelegatingClassLoader@0x0000000703c50b58
0x000000070a9fc320  1   3056    0x0000000709035198  dead    sun/reflect/DelegatingClassLoader@0x0000000703c50b58
0x000000070adcb4c8  1   3064    0x0000000709035198  dead    sun/reflect/DelegatingClassLoader@0x0000000703c50b58
0x000000070a913760  1   1888    0x0000000709035198  dead    sun/reflect/DelegatingClassLoader@0x0000000703c50b58
0x0000000709f3fd40  1   3032      null      dead    sun/reflect/DelegatingClassLoader@0x0000000703c50b58
0x000000070923ba78  1   3088    0x0000000709035260  dead    sun/reflect/DelegatingClassLoader@0x0000000703c50b58
0x000000070a88fff8  1   3048      null      dead    sun/reflect/DelegatingClassLoader@0x0000000703c50b58
0x000000070adcbc58  1   1888    0x0000000709035198  dead    sun/reflect/DelegatingClassLoader@0x0000000703c50b58

上述爲jmap的基本分析,共本人自己記錄學習使用. (本文演示的是使用JDK8演示)

 

找到一篇不錯的詳細的使用 鏈接附上.

 

OutOfMemoryError 原因: 常見的有以下幾種:

1.內存中加載的數據量過於龐大,如一次從數據庫取出過多數據;

2.集合類中有對對象的引用,使用完後未清空,使得JVM不能回收;

3.代碼中存在死循環或循環產生過多重複的對象實體;

4.使用的第三方軟件中的BUG;

5.啓動參數內存值設定的過小;

常見錯誤提示:

1.tomcat:java.lang.OutOfMemoryError: PermGen space

2.tomcat:java.lang.OutOfMemoryError: Java heap space

3.weblogic:Root cause of ServletException java.lang.OutOfMemoryError

4.resin:java.lang.OutOfMemoryError

5.java:java.lang.OutOfMemoryError

我遇到的是java.lang.OutOfMemoryError: PermGen space

解決:

1.應用服務器提示錯誤的解決: 把啓動參數內存值設置足夠大。

2.Java代碼導致錯誤的解決: 重點排查以下幾點:

1)檢查代碼中是否有死循環或遞歸調用。

2)檢查是否有大循環重複產生新對象實體。

3)檢查對數據庫查詢中,是否有一次獲得全部數據的查詢。一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。這個問題比較隱蔽,在上線前,數據庫中數據較少,不容易出問題,上線後,數據庫中數據多了,一次查詢就有可能引起內存溢出。因此對於數據庫查詢儘量採用分頁的方式查詢。

4 )檢查List、MAP等集合對象是否有使用完後,未清除的問題。List、MAP等集合對象會始終存有對對象的引用,使得這些對象不能被GC回收。

 

tomcat中java.lang.OutOfMemoryError: PermGen space異常處理

一、PermGen space PermGen space的全稱是Permanent Generation space,是指內存的永久保存區域, 這塊內存主要是被JVM存放Class和Meta信息的,Class在被Loader時就會被放到PermGen space中, 它和存放類實例(Instance)的Heap區域不同,GC(Garbage Collection)不會在主程序運行期對 PermGen space進行清理,所以如果你的應用中有很多CLASS的話,就很可能出現PermGen space錯誤, 這種錯誤常見在web服務器對JSP進行pre compile的時候。如果你的WEB APP下都用了大量的第三方jar, 其大小 超過了jvm默認的大小(4M)那麼就會產生此錯誤信息了。

解決方法: 手動設置MaxPermSize大小 修改TOMCAT_HOME/bin/catalina.sh 在“echo "Using CATALINA_BASE:   $CATALINA_BASE"”上面加入以下行: JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m 建議:將相同的第三方jar文件移置到tomcat/shared/lib目錄下,這樣可以達到減少jar 文檔重複佔用內存的目的。

回家以後再JDK7的服務器上解決一下 , 就OK了.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章