怎么排查内存溢出?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几次内存,把内存文件进行编号归档,便于后续内存整理分析。


分享到:


相關文章: