Java字节码4-使用Java-Agent实现一个JVM监控工具

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 list = new ArrayList();
            list.add("hello world");
        }
    }
} 
  

运行上述代码时,我们同样加上Agent。-javaagent:./my-agent.jar

运行结果:

你可能感兴趣的:(Java)