1.下载安装Jprofiler
Jprofiler 的官网下载 www.ej-technologies.com/ ,可以免费使用 10天,大家也可以找找绿色版,找不到自行处理
2.IDEA安装Jprofile插件
IDEA->File->settings->plugins->jprofiler, 搜到后直接安装
我的IDEA marketplace中是空的, 调试了半天还是没有软件,然后我就只能自己下载plugins 包解压来处理了
- 下载 idea-jprofiler 插件zip文件,找到自己的idea版本 plugins.jetbrains.com/plugin/253-…
- 下载完毕后解压, 然后把解压的文件夹 Jprofiler整个文件夹,复制到IDEA的插件plugins包中
- 找到 IDEA的插件安装位置 比如我的就是 E:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\plugins, 然后把解压的包复制进去
- 重启IDEA 然后就可以看到 右上角有 profile启动标记,意味着插件安装成功
3.IDEA调试Jprofiler启动程序
3.1 设置JVM启动参数
设置jvm参数 100M堆内存,启动程序
-verbose:gc -XX:+UseG1GC -Xms100M -Xmx100M -XX:+PrintGC -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:SurvivorRatio=8
应用程序代码, 程序代码简单SprintBoot项目外加一个测试Controller
package com.jzj.jvmtest.font;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class TestController {
@GetMapping("/ping")
private String ping() {
return "pong";
}
@GetMapping("/test")
private String test(Integer num) {
try {
byte[] b = null;
for (int i = 1; i <= num; i++) {
//设置 3M的对象
log.info("======== " + i + "次添加3M对象");
b = new byte[2 * 1024 * 1024];
Thread.sleep(3000);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return "success";
}
}
3.2 用Jprofile启动程序
点击 Profile 按钮,启动应用程序, 然后会弹窗,选择本地Jprofiler.exe的安装位置,配置完毕,启动
Initial profiling settings 选择第二个 CPU Recording ,其他默认即可,启动后就可以看到界面如下
3.3 Jprofile调试信息
堆内存信息 100M = 72M+30M 左右
切换Memory 查看信息
Eden区 一共 56M, 现在使用了 52M,空闲4M
老年代 一共37M,现在使用 11M, 空闲26M
幸存区Survivor区 一共8M,使用8M,空闲0M
元空间Metaspace 一共32M, 使用29M,空闲2M
4.并发请求CURL controller 看下内存的变化
我们采用ApiPost 请求 curl 127.0.0.1:8078/test?num=10 分别的往内存中添加对象来测试内存增长信息,查看对象增长到一定阶段GC日志信息
首先请求一次 , num =10 也就是循环10次,在内存中增加 10* new byte[2 * 1024 * 1024] = 20M的大小的内存文件 我们看下Jprofiler是不是这样
4.1 触发YongGC,Eden区清空
- 程序日志 触发YoungGC [GC pause (G1 Evacuation Pause) (young), 0.0084622 secs] [Parallel Time: 4.8 ms, GC Workers: 10]
- 触发了YoungGC, Eden区清空, 从Used 52M 变为 8M
- [Eden: 52.0M(52.0M)->0.0B(52.0M) Survivors: 8192.0K->8192.0K Heap: 71.4M(100.0M)->27.7M(100.0M)] YongGC结束,Head堆剩余 28M
看下Eden区 现在是多少 , 26.13M 差不多就是27M
4.2 看下Old区增长
我们知道,CURL创造了20M的数据, 我们看下Old区的变化曲线
- 刚开始 Old区一直比较稳定是 11M
- CURL后 开始慢慢增长, 每个台阶 2M ,差不多10次
- 一共增长 20M大小
- 然后触发 大对象YoungGC [GC pause (G1 Humongous Allocation) (young) (initial-mark), 0.0061738 secs]
- 回收大对象,Old区开始减小,最终稳定在使用20M左右
4.3 看下Survivor区信息
Survivor从一开始的打满8M,到最后还是打满 使用6M,回收了Survivor幸存区的部分对象
5.高并发测试CURL
请求 10次,轮次5轮,等于模拟50个请求,看下GC情况
执行结果
- Eden区在不停的增大,缩小,这些是G1动态调整的
- Old区经过mixedGC后,也会回收部分老年代空间
- 没有发生FullGC现象,因为G1几乎不会发生FullGC,MixedGC就会回收老年代
至此 使用IDEA来调试Jprofiler,并且根据不同的参数来进行JVM调优,我们算是入门了,下面我们针对jmap的dump文件进行 问题定位及内存溢出OOM的hprof文件分析