字节码基于JavaAgent的全链路监控四-JVM内存与GC信息

Posted 九师兄

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字节码基于JavaAgent的全链路监控四-JVM内存与GC信息相关的知识,希望对你有一定的参考价值。

1.概述

转载:基于JavaAgent的全链路监控四《JVM内存与GC信息》

2.案例简述

除了监控java方法的执行耗时,我们还需要获取应用实例的jvm内存与gc信息,以实时把控我们的服务器性能是否在安全范围。监控jvm内存与gc信息是非常重要的,尤其是在大促以及微博火热爆点的时候,我们需要根据监控信息进行扩容,以保证系统稳定。

2.1 JvmStack

package com.javaagent.bytebuddy.demo;


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;

/**
 * 博客:http://itstack.org
 * 论坛:http://bugstack.cn
 * 公众号:bugstack虫洞栈  {获取学习源码}
 * create by fuzhengwei on 2019
 */
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);
        
    



2.2 MyAgent


import java.lang.instrument.Instrumentation;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 博客:http://itstack.org
 * 论坛:http://bugstack.cn
 * 公众号:bugstack虫洞栈  {获取学习源码}
 * create by fuzhengwei on 2019
 */
public class MyAgent 

    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() 
                JvmStack.printMemoryInfo();
                JvmStack.printGCInfo();
                System.out.println("===================================================================================================");
            
        , 0, 5000, TimeUnit.MILLISECONDS);
    



2.3 测试类

package com.javaagent.bytebuddy.demo;

import java.util.LinkedList;
import java.util.List;


/**
 * -javaagent:/Users/lcc/IdeaProjects/lcc_work/test-byte-buddy/byte-buddy-v1x-javaagent-demo3/target/byte-buddy-v1x-javaagent-demo3-1.0-SNAPSHOT.jar=testsa
 *
 */
public class JvmStackTest 


    public static void main(String[] args) 
        while (true) 
            List<Object> list = new LinkedList<>();
            list.add("嗨!JavaAgent");
            list.add("嗨!JavaAgent");
            list.add("嗨!JavaAgent");
        
    

MANIFEST.MF 文件如下

 <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <addClasspath>true</addClasspath>
<!--                            <Premain-Class>com.javaagent.bytebuddy.MyPreMainAgent</Premain-Class>-->
                            <Premain-Class>com.javaagent.bytebuddy.demo.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>

2.4 测试结果

this is my agent:testargs

init: 192MB	 max: 2708MB	 used: 5MB	 committed: 184MB	 use rate: 3%
init: 2MB	 max: 0MB	 used: 5MB	 committed: 7MB	 use rate: 75%

name: PS Scavenge	 count:1	 took:2	 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]
===================================================================================================

init: 192MB	 max: 2708MB	 used: 249MB	 committed: 624MB	 use rate: 39%
init: 2MB	 max: 0MB	 used: 6MB	 committed: 7MB	 use rate: 78%

name: PS Scavenge	 count:32	 took:98	 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]
===================================================================================================

Process finished with exit code -1
 

以上是关于字节码基于JavaAgent的全链路监控四-JVM内存与GC信息的主要内容,如果未能解决你的问题,请参考以下文章

字节码基于JavaAgent的全链路监控五- ThreadLocal链路追踪

字节码基于JavaAgent的全链路监控六 基于jvmti定位java异常信 息

字节码JavaAgent的全链路监控篇二,通过字节码增加监控执行 耗时

基线监控:基于依赖关系的全链路智能监控报警

字节码javaagent 入门 案例 最简单的案例

字节码JavaAgent ByteBuddy操作监控方法 字节码