怎麼排查內存溢出?jmap 查看jvm堆內存信息

一、JVM內存區域概覽

JVM區域總體分兩類,heap區和非heap區

Heap區又分為:年輕代(Young Generation)和老年代(Old Generation)。

年輕代是所有新對象產生的地方。當年輕代內存空間被用完時,就會觸發垃圾回收。這個垃圾回收叫做Minor GC。

年輕代被分為3個部分—Eden區和兩個Survivor區。

老年代內存裡包含了長期存活的對象和經過多次Minor GC後依然存活下來的對象,通常會在老年代內存被佔滿時進行垃圾回收。老年代的垃圾收集叫做Major GC,Major GC通常是跟full GC是等價的,收集整個GC堆。

  • Eden Space(伊甸園);
  • Survivor Space(2個倖存者區);
  • Old Gen(老年代);

非Heap區又分:

  • Code Cache(代碼緩存區);
  • Perm Gen(永久代);JDK1.8之後被元空間替代;Perm Gen全稱是Permanent Generation space,稱之為永久代,其實指的就是這個方法區。
  • Jvm Stack(java虛擬機棧);
  • Local Method Statck(本地方法棧);
怎麼排查內存溢出?jmap 查看jvm堆內存信息



二、查看java堆的詳細信息

jmap是JDK自帶的工具軟件,主要用於打印指定Java進程(或核心文件、遠程調試服務器)的共享對象內存映射或堆內存細節。

執行命令:

jmap -heap PID

怎麼排查內存溢出?jmap 查看jvm堆內存信息

先查看應用對應的PID:

C:\Users\xxx>jps -l

18704 org.jetbrains.plugins.scala.nailgun.NailgunRunner

17832 org.jetbrains.jps.cmdline.Launcher

12412 com.sun.deploy.panel.ControlPanel

4028

41260 sun.tools.jps.Jps

41532 org.elasticsearch.bootstrap.Elasticsearch


下面是jmap 命令的輸出信息:

Attaching to process ID 31846, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 24.71-b01


using thread-local object allocation.

Parallel GC with 4 thread(s)//GC 方式


Heap Configuration: //堆內存初始化配置

MinHeapFreeRatio = 0 //對應jvm啟動參數-XX:MinHeapFreeRatio設置JVM堆最小空閒比率(default 40)

MaxHeapFreeRatio = 100 //對應jvm啟動參數 -XX:MaxHeapFreeRatio設置JVM堆最大空閒比率(default 70)

MaxHeapSize = 2082471936 (1986.0MB) //對應jvm啟動參數-XX:MaxHeapSize=設置JVM堆的最大大小

NewSize = 1310720 (1.25MB)//對應jvm啟動參數-XX:NewSize=設置JVM堆的‘新生代’的默認大小

MaxNewSize = 17592186044415 MB//對應jvm啟動參數-XX:MaxNewSize=設置JVM堆的‘新生代’的最大大小

OldSize = 5439488 (5.1875MB)//對應jvm啟動參數-XX:OldSize=:設置JVM堆的‘老生代’的大小

NewRatio = 2 //對應jvm啟動參數-XX:NewRatio=:‘新生代’和‘老生代’的大小比率

SurvivorRatio = 8 //對應jvm啟動參數-XX:SurvivorRatio=設置年輕代中Eden區與Survivor區的大小比值

PermSize = 21757952 (20.75MB) //對應jvm啟動參數-XX:PermSize=:設置JVM堆的‘永生代’的初始大小

MaxPermSize = 85983232 (82.0MB)//對應jvm啟動參數-XX:MaxPermSize=:設置JVM堆的‘永生代’的最大大小

G1HeapRegionSize = 0 (0.0MB)

怎麼排查內存溢出?jmap 查看jvm堆內存信息

Heap Usage://堆內存使用情況

PS Young Generation

Eden Space://Eden區內存分佈

capacity = 33030144 (31.5MB)//Eden區總容量

used = 1524040 (1.4534378051757812MB) //Eden區已使用

free = 31506104 (30.04656219482422MB) //Eden區剩餘容量

4.614088270399305% used //Eden區使用比率

From Space: //其中一個Survivor區的內存分佈

capacity = 5242880 (5.0MB)

used = 0 (0.0MB)

free = 5242880 (5.0MB)

0.0% used

To Space: //另一個Survivor區的內存分佈

capacity = 5242880 (5.0MB)

used = 0 (0.0MB)

free = 5242880 (5.0MB)

0.0% used

PS Old Generation //當前的Old區內存分佈

capacity = 86507520 (82.5MB)

used = 0 (0.0MB)

free = 86507520 (82.5MB)

0.0% used

PS Perm Generation//當前的 “永生代” 內存分佈

capacity = 22020096 (21.0MB)

used = 2496528 (2.3808746337890625MB)

free = 19523568 (18.619125366210938MB)

11.337498256138392% used


670 interned Strings occupying 43720 bytes.



三、查看堆內存(histogram)中的對象數量及大小

執行命令: jmap -histo 3331

num #instances #bytes class name

編號 個數 字節 類名

----------------------------------------------

1: 7 1322080 [I

2: 5603 722368

3: 5603 641944

4: 34022 544352 java.lang.Integer

5: 371 437208

6: 336 270624

7: 371 253816

怎麼排查內存溢出?jmap 查看jvm堆內存信息


四、將內存使用的詳細情況輸出到文件

執行命令: jmap -dump:format=b,file=heapDump 6900

怎麼排查內存溢出?jmap 查看jvm堆內存信息


然後用jhat命令可以參看 jhat -port 5000 heapDump 在瀏覽器中訪問:http://localhost:5000/ 查看詳細信息。


這個命令執行,JVM會將整個heap的信息dump寫入到一個文件,heap如果比較大的話,就會導致這個過程比較耗時,並且執行的過程中為了保證dump的信息是可靠的,所以會暫停應用。

怎麼排查內存溢出?jmap 查看jvm堆內存信息


五、小結

1.如果程序內存不足或者頻繁GC,很有可能存在內存洩露情況,這時候就要藉助Java堆Dump查看對象的情況。

2.要製作堆Dump可以直接使用jvm自帶的jmap命令。

3.可以先使用jmap -heap命令查看堆的使用情況,看一下各個堆空間的佔用情況。

4.使用jmap -histo:[live]查看堆內存中的對象的情況。如果有大量對象在持續被引用,並沒有被釋放掉,那就產生了內存洩露,就要結合代碼,把不用的對象釋放掉。

5.也可以使用 jmap -dump:format=b,file=命令將堆信息保存到一個文件中,再借助jhat命令查看詳細內容。

6.在內存出現洩露、溢出或者其它前提條件下,建議多dump幾次內存,把內存文件進行編號歸檔,便於後續內存整理分析。


分享到:


相關文章: