zoukankan      html  css  js  c++  java
  • arthas与jvm-sandbox

    arthas与jvm-sandbox是阿里开源的JVM工具,都能够attach到一个正在运行的Java进程中,可以查看运行时的一些信息,并且可以通过对字节码的修改,来实现一些高级功能。 
    arthas和jvm-sandbox之所以能实现这些功能,主要依赖的有Java agent和ASM字节码修改。
    1. java agent是Jdk1.5之后引入的技术,可以随Java进程一起启动,或者attach到一个已经运行的Java进程。 在attach到进程后,Java本身提供了一些类(Instrumentation), 可以获取到一些运行信息,并且也提供了一些方法,可以对字节码进行干预。
    2. ASM可以生成或者修改字节码, 配合Instrumentation的addTransformer()和retransformClasses()方法,可以完成对字节码的修改。 
     
    为了便于对着两个技术的理解,我这里简化了一下,实现了一个demo。 
    业务类:
    package com.demo;
    
    public class Service {
    public void dosome() {
    System.out.println(
    "do some..."); } }
    package com.demo;
    
    import java.lang.management.ManagementFactory;
    import java.util.Scanner;
    
    /**
     * Hello world!
     */
    public class App {
    
        public static void main(String[] args) {
    
            // 获取pid  供agent使用
            String name = ManagementFactory.getRuntimeMXBean().getName();
            String pid = name.split("@")[0];
            System.out.println("应用程序进程Id:" + pid);
    
            // 注意这里实例化,类加载一次, 之后没有再加载
            Service service = new Service();
    
            // 键盘上输入F值,模拟业务执行
            Scanner scanner = new Scanner(System.in);
            System.out.println("按 F 执行程序");
    
            while (true) {
                String cmd = scanner.nextLine();
                if ("f".equalsIgnoreCase(cmd)) {
                    service.dosome();
                }
            }
        }
    }

    代理类:

    package com.agent;
    
    import java.lang.instrument.Instrumentation;
    import java.lang.instrument.UnmodifiableClassException;
    
    /**
     * Hello world!
     */
    public class AgentLauncher {
    
        public static void premain(String featureString, Instrumentation inst) {
            System.out.println("pre main");
        }
    
        /**
         * 通过attach的方式
         */
        public static void agentmain(String featureString, Instrumentation inst) throws UnmodifiableClassException {
            System.out.println("agent!!! 增强业务方法");
            // 增强
            MyClassFileTransformer myClassFileTransformer = new MyClassFileTransformer();
            // 添加到Instrumentation
            inst.addTransformer(myClassFileTransformer, true);
    
            // 找到需要重新加载的类
            Class<?>[] loadeds = inst.getAllLoadedClasses();
            Class<?> targetClass = null;
            for (Class<?> loaded : loadeds) {
                if (loaded.getName().equals("com.demo.Service")) {
                    targetClass = loaded;
                }
            }
            // 重新加载类, 保证动态的增强类生效
            inst.retransformClasses(targetClass);
            System.out.println("增强完毕,请重新执行业务方法");
    
        }
    
    
    }

    最后是attach

    package com.attach;
    
    import com.sun.tools.attach.VirtualMachine;
    
    /**
     * Hello world!
     */
    public class App {
    
        public static void main(String[] args) throws Exception {
    
            String targetJvmPid = "912"; // 业务进程ID
            if (args != null) {
                if (args.length > 0) {
                    targetJvmPid = args[0];
                }
            }
    
            if (targetJvmPid != null) {
                VirtualMachine vmObj = null;
                try {
                    vmObj = VirtualMachine.attach(targetJvmPid);
                    if (vmObj != null) {
                        // 加载agent的jar包, 需要先在agent项目中执行 maven package命令生成
                        vmObj.loadAgent("D:\jar\agent-1.0-jar-with-dependencies.jar");
                    }
    
                } finally {
                    if (null != vmObj) {
                        vmObj.detach();
                    }
                }
            }
        }
    }

    最后整体的运行效果如下:

    第一个红框是业务类正常运行的结果

    第二个红框执行attach的效果

    第三个是重新运行业务代码的效果,可以看到方法在执行前后加了一个start和end.

    完整的代码参考:https://github.com/zhaoyb/java-agent

  • 相关阅读:
    Tomcat系列教材 (一)- 教程
    反射机制系列教材 (四)- 调用方法
    反射机制系列教材 (五)- 有什么用
    反射机制系列教材 (三)- 访问属性
    【算法竞赛进阶指南】車的放置(行列模型二分图最大匹配+匈牙利算法)
    【算法竞赛进阶指南】棋盘覆盖(二分图最大匹配)
    【算法竞赛进阶指南】关押罪犯(二分+染色法判断二分图)
    数值计算实验三——拉格朗日插值和牛顿插值
    LDUOJ——2020级C语言测试1(顺序选择)
    codeforces859——C. Pie Rules(思维+DP)
  • 原文地址:https://www.cnblogs.com/beyondbit/p/15272819.html
Copyright © 2011-2022 走看看