如何使用serviceability agent调试进程

背景介绍

首先,我们有这样一个进程,我们希望在Example01运行起来之后,通过HotSpotAgent来观测它的执行情况,比如启动参数、内存、CPU、垃圾回收情况等。

package com.jeff.study.debugger.sa;

public class Example01 {
    public int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) throws InterruptedException {
        Example01 example01 = new Example01();
        for (int i = 0; i < 1000; i++) {
            int res = example01.add(i, i*i);
            System.out.println(res+"---"+new Date());
            Thread.sleep(1000);
        }

    }
}

如何做到呢?步骤很简单,就是启动如下进程,attach刚才的Example01进程的PID。

package com.jeff.study.debugger.sa;

import sun.jvm.hotspot.HotSpotAgent;
import sun.jvm.hotspot.runtime.VM;

public class VMMonitor {
    public static void main(String[] args) {
         int pid = 46449;
        HotSpotAgent hotSpotAgent = new HotSpotAgent();
        hotSpotAgent.attach(pid);
        VM vm = VM.getVM();
        VM.Flag[] commandLineFlags = vm.getCommandLineFlags();
        for (VM.Flag flag : commandLineFlags) {
            System.out.println(flag.getName() + ":" + flag.getValue());
        }
        Thread.sleep(10000);
        System.out.println("------------");
        String cpu = vm.getCPU();
        System.out.println("CPU:"+cpu);
        System.out.println("------------");

    }
}

但是,对于不同的jdk版本却有不同的操作方式,我们分别介绍jdk11和jdk8.

JDK11

这里我安装的版本是11.0.25:
在这里插入图片描述
通过上述的VmMonitor.java我们看到导入了两个类:

import sun.jvm.hotspot.HotSpotAgent;
import sun.jvm.hotspot.runtime.VM;

这两个类实际上是由一个叫做sd-jdi.jar的文件提供,对于JDK11来说,这个文件并没有直接提供,而是***/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/lib***目录的src.zip中。
在这里插入图片描述

打包sa-jdi.jar

首先就是要解压src.zip得到一个src目录,我们关注的是jdk.hotspot.agent目录:
在这里插入图片描述
进入之后,执行如下命令:

javac -d classes com/sun/java/swing/action/*.java com/sun/java/swing/ui/*.java sun/jvm/hotspot/*.java

会将java文件编译到classes目录,进入classes目录:

  1. 创建一个META-INF/MANIFEST.MF文件,内容如下:
    在这里插入图片描述
Manifest-Version: 1.0
Created-By: 11.0.25 (Oracle Corporation)
  1. 创建一个sa.properties文件,内容如下:
sun.jvm.hotspot.runtime.VM.saBuildVersion=11.0.25+9-LTS-256

  1. 打包为sa-jdi.jar
jar -cvfm sa-jdi.jar META-INF/MANIFEST.MF *

导入到IDEA->File->Project Structure


注意,IDEA环境需要统一为jdk11的版本:

在这里插入图片描述

添加编译参数

-parameters
--add-exports
jdk.hotspot.agent/sun.jvm.hotspot.runtime=ALL-UNNAMED
--add-exports
jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED
--add-exports
jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED

在这里插入图片描述

看效果

在这里插入图片描述

启动Example01进程,PID是46449.然后启动attach进程,attach成功之后,我们这里休眠了10s
可以观察到Example01进程中间有10s左右时间是没有打印日志的,说明进程被暂停了!
也就是:attach操作会导致业务线程发生STW
在这里插入图片描述

JDK8

jdk8本身在目录**/Library/Java/JavaVirtualMachines/jdk1.8.0_341.jdk/Contents/Home/lib**下就已经有了sa-jdi.jar,这一点比jdk11要方便很多,直接导入idea的Library下即可:
在这里插入图片描述

在这里插入图片描述
但是当真正执行时,却出现如下报错!也找了很多解决方式,主要有两种说法:

  • 升级jdk版本到9以上(jdk的bug)
  • 使用windows系统运行,是macOS系统原因

Exception in thread “main” sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: Can’t attach symbolicator to the process
at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal$BsdDebuggerLocalWorkerThread.execute(BsdDebuggerLocal.java:169)
at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.attach(BsdDebuggerLocal.java:287)
at sun.jvm.hotspot.HotSpotAgent.attachDebugger(HotSpotAgent.java:671)
at sun.jvm.hotspot.HotSpotAgent.setupDebuggerDarwin(HotSpotAgent.java:659)
at sun.jvm.hotspot.HotSpotAgent.setupDebugger(HotSpotAgent.java:341)
at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:304)
at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140)
at com.jeff.study.debugger.sa.VMMonitor.main(VMMonitor.java:10)
Caused by: sun.jvm.hotspot.debugger.DebuggerException: Can’t attach symbolicator to the process
at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.attach0(Native Method)
at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.access$100(BsdDebuggerLocal.java:65)
at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal 1 A t t a c h T a s k . d o i t ( B s d D e b u g g e r L o c a l . j a v a : 278 ) a t s u n . j v m . h o t s p o t . d e b u g g e r . b s d . B s d D e b u g g e r L o c a l 1AttachTask.doit(BsdDebuggerLocal.java:278) at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal 1AttachTask.doit(BsdDebuggerLocal.java:278)atsun.jvm.hotspot.debugger.bsd.BsdDebuggerLocalBsdDebuggerLocalWorkerThread.run(BsdDebuggerLocal.java:144)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

公众号: 江南烟雨中

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值