【JVM】Jmap与MAT分析内存溢出

文章目录

  • 一. 内存溢出模拟以及导出内存映像文件
    • 1.1 自动导出内存映像文件
    • 1.2 jmap -dump 导出内存映像文件
    • 1.3. jmap -heap 命令显示堆信息
  • 二. MAT 分析内存映像文件

一. 内存溢出模拟以及导出内存映像文件

  1. 文末贴详细代码,这里给出部分代码:
@RestController
@RequestMapping("memory")
public class MemoryController {
	
	private List<User>  userList = new ArrayList<User>();
	private List<Class<?>>  classList = new ArrayList<Class<?>>();
	
	/**
	 * 1. 堆内存溢出
	 * 	循环往userList 里增添对象,因为 MemoryController对象不会回收,则userList肯定也不会回收
	 *  jvm参数:-Xmx32M -Xms32M
	 * */
	@GetMapping("/heap")
	public String heap() {
		int i=0;
		while(true) {
			userList.add(new User(i++, UUID.randomUUID().toString()));
		}
	}
	
	
	/**
	 * 1. 非堆内存溢出
	 *    产生大量的类对象填满方法区
	 * jvm参数:-XX:MetaspaceSize=32M -XX:MaxMetaspaceSize=32M
	 * */
	@GetMapping("/nonheap")
	public String nonheap() {
		while(true) {
			classList.addAll(Metaspace.createClasses());
		}
	}
	
}

1.1 自动导出内存映像文件

内存溢出时自动导出 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./

  1. 配置jvm参数并启动
    【JVM】Jmap与MAT分析内存溢出_第1张图片
    其中,-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./表示内存溢出时自动导出内存映像文件文件。
  2. 访问http://localhost:8080/memory/heap 接口会发现内存溢出。
    在这里插入图片描述
  3. 在项目根目录下会发现自动导出的内存映像文件
    【JVM】Jmap与MAT分析内存溢出_第2张图片

住:这种自动导出的方式在生产环境中并不常用,因为有时候会影响性能以及卡顿问题,最好用 jmap -dump导出

1.2 jmap -dump 导出内存映像文件

在上节的第2步之后,cmd窗口下分别运行:

jps -l  // 打印虚拟机进程以及对应pid
jmap -dump:format=b,file=heap.hprof 16892  // 导出内存映像文件到当前目录

【JVM】Jmap与MAT分析内存溢出_第3张图片
在这里插入图片描述

1.3. jmap -heap 命令显示堆信息

jmap -heap 命令显示堆的详细信息,比如使用哪种回收器、参数配置、分代状况等,结果注释如下:

C:\Users\libin\Desktop>jmap -heap 16892
Attaching to process ID 16892, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.181-b13

using thread-local object allocation.
Parallel GC with 4 thread(s) // 使用 Parallel 并行收集器

Heap Configuration:
   MinHeapFreeRatio         = 0    //JVM最小空闲比率 可由-XX:MinHeapFreeRatio=参数设置, jvm heap 在使用率小于 n 时 ,heap 进行收缩
   MaxHeapFreeRatio         = 100  //JVM最大空闲比率 可由-XX:MaxHeapFreeRatio=参数设置, jvm heap 在使用率大于 n 时 ,heap 进行扩张 
   MaxHeapSize              = 2095054848 (1998.0MB) //JVM堆的最大大小 可由-XX:MaxHeapSize=参数设置
   NewSize                  = 44040192 (42.0MB) //JVM新生代的默认大小 可由-XX:NewSize=参数设置
   MaxNewSize               = 698351616 (666.0MB) //JVM新生代的最大大小 可由-XX:MaxNewSize=参数设置
   OldSize                  = 88080384 (84.0MB) //JVM老生代的默认大小 可由-XX:OldSize=参数设置 
   NewRatio                 = 2 //新生代:老生代(的大小)=1:2 可由-XX:NewRatio=参数指定New Generation与Old Generation heap size的比例。
   SurvivorRatio            = 8 //survivor:eden = 1:8,即survivor space是新生代大小的1/(8+2)[因为有两个survivor区域] 可由-XX:SurvivorRatio=参数设置
   MetaspaceSize            = 21807104 (20.796875MB) //元空间的默认大小,超过此值就会触发Full GC 可由-XX:MetaspaceSize=参数设置
   CompressedClassSpaceSize = 1073741824 (1024.0MB) //类指针压缩空间的默认大小 可由-XX:CompressedClassSpaceSize=参数设置
   MaxMetaspaceSize         = 17592186044415 MB //元空间的最大大小 可由-XX:MaxMetaspaceSize=参数设置
   G1HeapRegionSize         = 0 (0.0MB) //使用G1垃圾收集器的时候,堆被分割的大小 可由-XX:G1HeapRegionSize=参数设置


Heap Usage:
PS Young Generation //新生代堆粉笔情况
Eden Space: //Eden 区域
   capacity = 7864320 (7.5MB)
   used     = 7864320 (7.5MB)
   free     = 0 (0.0MB)
   100.0% used
From Space: // 其中一个Survivor区域
   capacity = 1572864 (1.5MB)
   used     = 0 (0.0MB)
   free     = 1572864 (1.5MB)
   0.0% used
To Space: // 另一个Survivor区域
   capacity = 1572864 (1.5MB)
   used     = 0 (0.0MB)
   free     = 1572864 (1.5MB)
   0.0% used
PS Old Generation //老生代区域分配
   capacity = 22544384 (21.5MB)
   used     = 22228088 (21.19835662841797MB)
   free     = 316296 (0.30164337158203125MB)
   98.59700757403706% used

13418 interned Strings occupying 1903808 bytes.

二. MAT 分析内存映像文件

MAT可以用于查找内存泄露以及查看内存消耗情况,具体就是可以查看每个类的使用情况以及内存占用情况,从而分析问题。

使用方式参考:Java程序内存分析:使用mat工具分析内存占用l

  1. 启动MAT并导入上章的 内存映像文件,默认会进入下面界面,主要使用圈出来的两个工具。
    【JVM】Jmap与MAT分析内存溢出_第4张图片

Histogram可以列出内存中的对象,对象的个数以及大小。

Dominator Tree可以列出那个线程,以及线程下面的那些对象占用的空间。

Top consumers通过图形列出最大的object。

Leak Suspects通过MA自动分析泄漏的原因。

  1. Histogram 界面示例
    在这里插入图片描述

Class Name : 类名称,java类名

Objects : 类的对象的数量,这个对象被创建了多少个

Shallow Heap :一个对象内存的消耗大小,不包含对其他对象的引用

Retained Heap :是shallow Heap的总和,也就是该对象被GC之后所能回收到内存的总和

  1. Dominator Tree 界面示例
    可以看出占用内存最大的 是User对象
    【JVM】Jmap与MAT分析内存溢出_第5张图片
    延伸阅读:
    Shallow heap & Retained heap解释

你可能感兴趣的:(jvm)