基于Java的agent 技术获取JVM和GC信息

有时候我们需要对线上的JVM信息以及GC信息进行统计。基于Java的agent 技术可以实现。

1. 新建agent 相关的类

  1. 工具类
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);
        }
    }

}

  1. 对外暴露的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 包打包

  1. 修改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>
  1. 打包
mvn clean package
  1. 打包包,解压后查看

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]

...
posted @ 2023-04-04 22:37  QiaoZhi  阅读(165)  评论(0编辑  收藏  举报