基于Java的agent 技术获取JVM和GC信息
有时候我们需要对线上的JVM信息以及GC信息进行统计。基于Java的agent 技术可以实现。
1. 新建agent 相关的类
- 工具类
package org.example.jvmdebug;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.Arrays;
import java.util.List;
public class JvmStack {
private static final long MB = 1048576L;
static void printMemoryInfo() {
MemoryMXBean memory = ManagementFactory.getMemoryMXBean();
MemoryUsage headMemory = memory.getHeapMemoryUsage();
String info = String.format("\ninit: %s\t max: %s\t used: %s\t committed: %s\t use rate: %s\n",
headMemory.getInit() / MB + "MB",
headMemory.getMax() / MB + "MB", headMemory.getUsed() / MB + "MB",
headMemory.getCommitted() / MB + "MB",
headMemory.getUsed() * 100 / headMemory.getCommitted() + "%"
);
System.out.print(info);
MemoryUsage nonheadMemory = memory.getNonHeapMemoryUsage();
info = String.format("init: %s\t max: %s\t used: %s\t committed: %s\t use rate: %s\n",
nonheadMemory.getInit() / MB + "MB",
nonheadMemory.getMax() / MB + "MB", nonheadMemory.getUsed() / MB + "MB",
nonheadMemory.getCommitted() / MB + "MB",
nonheadMemory.getUsed() * 100 / nonheadMemory.getCommitted() + "%"
);
System.out.println(info);
}
static void printGCInfo() {
List<GarbageCollectorMXBean> garbages = ManagementFactory.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean garbage : garbages) {
String info = String.format("name: %s\t count:%s\t took:%s\t pool name:%s",
garbage.getName(),
garbage.getCollectionCount(),
garbage.getCollectionTime(),
Arrays.deepToString(garbage.getMemoryPoolNames()));
System.out.println(info);
}
}
}
- 对外暴露的agent
package org.example.jvmdebug;
import java.lang.instrument.Instrumentation;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class MyAgent {
private static AtomicInteger TIMES = new AtomicInteger();
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("this is my agent:" + agentArgs);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("===================================================================================================" + TIMES.addAndGet(1));
JvmStack.printMemoryInfo();
JvmStack.printGCInfo();
}
}, 0, 5, TimeUnit.SECONDS);
}
}
2. 将jar 包打包
- 修改pom
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<addClasspath>true</addClasspath>
<Premain-Class>org.example.jvmdebug.MyAgent</Premain-Class>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
- 打包
mvn clean package
- 打包包,解压后查看
META-INF/MANIFEST.MF文件如下:
Manifest-Version: 1.0
addDefaultSpecificationEntries: true
addClasspath: true
Premain-Class: org.example.jvmdebug.MyAgent
Archiver-Version: Plexus Archiver
Built-By: xxx
Can-Redefine-Classes: true
addDefaultImplementationEntries: true
Can-Retransform-Classes: true
Created-By: Apache Maven 3.8.1
Build-Jdk: 1.8.0_351
3. 测试
package org.example.jvmdebug;
public class JvmStackTest {
private static final int _MB = 1024 * 1024;
public static void main(String[] args) throws InterruptedException {
while (true) {
Thread.sleep(5 * 1000);
byte[] bytes = new byte[10 * _MB];
}
}
}
修改JVM参数增加agent:
-javaagent:/Users/xxx/Desktop/jvmdebug/mvnpro-1.0-SNAPSHOT.jar
查看日志:
this is my agent:null
===================================================================================================1
init: 256MB max: 3641MB used: 5MB committed: 245MB use rate: 2%
init: 2MB max: 0MB used: 5MB committed: 7MB use rate: 68%
name: PS Scavenge count:0 took:0 pool name:[PS Eden Space, PS Survivor Space]
name: PS MarkSweep count:0 took:0 pool name:[PS Eden Space, PS Survivor Space, PS Old Gen]
===================================================================================================2
init: 256MB max: 3641MB used: 7MB committed: 245MB use rate: 3%
init: 2MB max: 0MB used: 5MB committed: 7MB use rate: 69%
name: PS Scavenge count:0 took:0 pool name:[PS Eden Space, PS Survivor Space]
name: PS MarkSweep count:0 took:0 pool name:[PS Eden Space, PS Survivor Space, PS Old Gen]
===================================================================================================3
init: 256MB max: 3641MB used: 17MB committed: 245MB use rate: 7%
init: 2MB max: 0MB used: 5MB committed: 7MB use rate: 69%
name: PS Scavenge count:0 took:0 pool name:[PS Eden Space, PS Survivor Space]
name: PS MarkSweep count:0 took:0 pool name:[PS Eden Space, PS Survivor Space, PS Old Gen]
===================================================================================================4
init: 256MB max: 3641MB used: 27MB committed: 245MB use rate: 11%
init: 2MB max: 0MB used: 5MB committed: 7MB use rate: 70%
name: PS Scavenge count:0 took:0 pool name:[PS Eden Space, PS Survivor Space]
name: PS MarkSweep count:0 took:0 pool name:[PS Eden Space, PS Survivor Space, PS Old Gen]
===================================================================================================5
init: 256MB max: 3641MB used: 37MB committed: 245MB use rate: 15%
init: 2MB max: 0MB used: 5MB committed: 7MB use rate: 70%
name: PS Scavenge count:0 took:0 pool name:[PS Eden Space, PS Survivor Space]
name: PS MarkSweep count:0 took:0 pool name:[PS Eden Space, PS Survivor Space, PS Old Gen]
===================================================================================================6
init: 256MB max: 3641MB used: 47MB committed: 245MB use rate: 19%
init: 2MB max: 0MB used: 5MB committed: 7MB use rate: 70%
name: PS Scavenge count:0 took:0 pool name:[PS Eden Space, PS Survivor Space]
name: PS MarkSweep count:0 took:0 pool name:[PS Eden Space, PS Survivor Space, PS Old Gen]
===================================================================================================7
init: 256MB max: 3641MB used: 57MB committed: 245MB use rate: 23%
init: 2MB max: 0MB used: 5MB committed: 7MB use rate: 70%
name: PS Scavenge count:0 took:0 pool name:[PS Eden Space, PS Survivor Space]
name: PS MarkSweep count:0 took:0 pool name:[PS Eden Space, PS Survivor Space, PS Old Gen]
===================================================================================================8
init: 256MB max: 3641MB used: 11MB committed: 245MB use rate: 4%
init: 2MB max: 0MB used: 5MB committed: 7MB use rate: 70%
name: PS Scavenge count:1 took:8 pool name:[PS Eden Space, PS Survivor Space]
name: PS MarkSweep count:0 took:0 pool name:[PS Eden Space, PS Survivor Space, PS Old Gen]
...
【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2019-04-04 dubbo直连提供者 & 只订阅 & 只注册
2019-04-04 dubbo线程模型
2018-04-04 quartz入门
2018-04-04 quartz的简介
2018-04-04 Spring注解@Resource和@Autowired区别对比、spring扫描的默认bean的Id、程序获取spring容器对象