一、概述
在前面几节当中,我们构造了多个Agent。Agent由于是在main方法之前执行,我们可以做很多事情。
本节中,我们将使用Agent技术来监控应用程序的JVM内存和GC信息。
二、实现
1、修改pom.xml
javassist
javassist
3.12.1.GA
jar
net.bytebuddy
byte-buddy
1.5.7
net.bytebuddy
byte-buddy-agent
1.5.7
my-agent
org.apache.maven.plugins
maven-jar-plugin
2.3.2
true
src/main/resources/META-INF/MANIFEST.MF
org.apache.maven.plugins
maven-shade-plugin
package
shade
javassist:javassist:jar:
net.bytebuddy:byte-buddy:jar:
net.bytebuddy:byte-buddy-agent:jar:
org.apache.maven.plugins
maven-compiler-plugin
1.7
1.7
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 list = new ArrayList();
list.add("hello world");
}
}
}
运行上述代码时,我们同样加上Agent。-javaagent:./my-agent.jar
运行结果: