JVM系列(二十二) JVM调优实战-IDEA使用Jprofile实时分析

1,574 阅读2分钟

1.下载安装Jprofiler

Jprofiler 的官网下载 www.ej-technologies.com/ ,可以免费使用 10天,大家也可以找找绿色版,找不到自行处理

2.IDEA安装Jprofile插件

IDEA->File->settings->plugins->jprofiler, 搜到后直接安装

image.png

我的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启动标记,意味着插件安装成功

image.png

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";

    }
}

image.png

3.2 用Jprofile启动程序

点击 Profile 按钮,启动应用程序, 然后会弹窗,选择本地Jprofiler.exe的安装位置,配置完毕,启动

image.png

Initial profiling settings 选择第二个 CPU Recording ,其他默认即可,启动后就可以看到界面如下

image.png

3.3 Jprofile调试信息

堆内存信息 100M = 72M+30M 左右

image.png

切换Memory 查看信息

image.png

Eden区 一共 56M, 现在使用了 52M,空闲4M

image.png

老年代 一共37M,现在使用 11M, 空闲26M image.png

幸存区Survivor区 一共8M,使用8M,空闲0M

image.png

元空间Metaspace 一共32M, 使用29M,空闲2M

image.png

4.并发请求CURL controller 看下内存的变化

我们采用ApiPost 请求 curl 127.0.0.1:8078/test?num=10 分别的往内存中添加对象来测试内存增长信息,查看对象增长到一定阶段GC日志信息

image.png

首先请求一次 , 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

image.png

看下Eden区 现在是多少 , 26.13M 差不多就是27M

image.png

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左右

image.png

4.3 看下Survivor区信息

Survivor从一开始的打满8M,到最后还是打满 使用6M,回收了Survivor幸存区的部分对象

image.png

5.高并发测试CURL

请求 10次,轮次5轮,等于模拟50个请求,看下GC情况

image.png

执行结果

  • Eden区在不停的增大,缩小,这些是G1动态调整的
  • Old区经过mixedGC后,也会回收部分老年代空间
  • 没有发生FullGC现象,因为G1几乎不会发生FullGC,MixedGC就会回收老年代

image.png

image.png


至此 使用IDEA来调试Jprofiler,并且根据不同的参数来进行JVM调优,我们算是入门了,下面我们针对jmap的dump文件进行 问题定位及内存溢出OOM的hprof文件分析