Java字节码系列
Java字节码1-Agent简单上手
Java字节码2-instrument初体验
Java字节码3-使用ByteBuddy实现一个Java-Agent
Java字节码4-使用Java-Agent实现一个JVM监控工具
本系列代码可见:https://github.com/hawkingfoo/demo-agent
一、概述
在前面几节当中,我们构造了多个Agent。Agent由于是在main
方法之前执行,我们可以做很多事情。
本节中,我们将使用Agent技术来监控应用程序的JVM内存和GC信息。
二、实现
1、修改pom.xml
<dependencies>
<dependency>
<groupId>javassistgroupId>
<artifactId>javassistartifactId>
<version>3.12.1.GAversion>
<type>jartype>
dependency>
<dependency>
<groupId>net.bytebuddygroupId>
<artifactId>byte-buddyartifactId>
<version>1.5.7version>
dependency>
<dependency>
<groupId>net.bytebuddygroupId>
<artifactId>byte-buddy-agentartifactId>
<version>1.5.7version>
dependency>
dependencies>
<build>
<finalName>my-agentfinalName>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-jar-pluginartifactId>
<version>2.3.2version>
<configuration>
<archive>
<index>trueindex>
<manifestFile>src/main/resources/META-INF/MANIFEST.MFmanifestFile>
<manifest>
<addDefaultImplementationEntries/>
manifest>
archive>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-shade-pluginartifactId>
<executions>
<execution>
<phase>packagephase>
<goals>
<goal>shadegoal>
goals>
execution>
executions>
<configuration>
<artifactSet>
<includes>
<include>javassist:javassist:jar:include>
<include>net.bytebuddy:byte-buddy:jar:include>
<include>net.bytebuddy:byte-buddy-agent:jar:include>
includes>
artifactSet>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<source>1.7source>
<target>1.7target>
configuration>
plugin>
plugins>
build>
2、实现一个Agent
Agent的构造比较简单,我们只需要在premain
方法中,加入一个线程池。其功能是每隔5秒输出一次内存信息和GC信息。
public class MyAgent {
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("this is an perform monitor agent.");
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
public void run() {
Metric.printMemoryInfo();
Metric.printGCInfo();
}
}, 0, 5000, TimeUnit.MILLISECONDS);
}
}
3、获取JVM 内存以及GC信息
public class Metric {
private static final long MB = 1048576L
public 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)
}
public static void printGCInfo() {
List 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)
}
}
}
三、运行
public class AgentTest {
public static void main(String[] args) throws Exception {
boolean is = true;
while (is) {
List