zoukankan      html  css  js  c++  java
  • java agent 运行期织入【yetdone】

    https://www.cnblogs.com/silyvin/p/11260965.html,

    此前对javaagent的使用是在类加载期,需要重启应用才能织入,本次实践java agent运行期织入

    1. premain是静态修改,在类加载之前修改; attach是动态修改,在类加载后修改
    2. 要使premain生效重启应用,而attach不重启应用即可修改字节码并让其重新加载

    可以看到attach的方式更加强大,其核心原理首先是找到相关的进程id, 然后根据进程id去动态修改相关字节码

    还是参考这篇文章:https://www.jianshu.com/p/b2d09a78678d

    package agent;
    //
    //import com.sun.tools.attach.VirtualMachine;无法通过编译
    import javassist.ClassPool;
    import javassist.CtBehavior;
    import javassist.CtClass;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.lang.instrument.ClassFileTransformer;
    import java.lang.instrument.IllegalClassFormatException;
    import java.lang.instrument.Instrumentation;
    import java.lang.instrument.UnmodifiableClassException;
    import java.lang.reflect.Method;
    import java.security.ProtectionDomain;
    
    /**
     * https://www.cnblogs.com/silyvin/p/11260965.html
     * https://www.cnblogs.com/silyvin/p/11336727.html
     * Created by sunyuming on 19/7/28.
     */
    public class MyTransformer implements ClassFileTransformer {
    
        private ClassPool classPool = new ClassPool(true);
    
        @Override
        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
    
            if(className.equals("agent/MyClient")) {
                System.out.println("类 " + className);
                try {
                    CtClass ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
                    for(CtBehavior ctBehavior : ctClass.getDeclaredBehaviors()) {
                        if(ctBehavior.getLongName().equals("agent.MyClient.print()")) {
                            System.out.println("开始处理方法 " + ctBehavior.getLongName());
                            ctBehavior.insertBefore("System.out.println("前置aop");");
                            ctBehavior.insertAfter("System.out.println("后置aop");");
                        }
                    }
                    return ctClass.toBytecode();
    
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            } else
                return null;
    
        }
    
        public static void agentmain(String agentArgs, Instrumentation inst)
                throws ClassNotFoundException, UnmodifiableClassException,
                InterruptedException {
            System.out.println("Agent Main start " + agentArgs);
            inst.addTransformer(new MyTransformer(), true);
            inst.retransformClasses(MyClient.class);
        }
    
        public static void premain(String args, Instrumentation instrumentation) {
            System.out.println("开始premain " + args);
            ClassFileTransformer classFileTransformer = new MyTransformer();
            instrumentation.addTransformer(classFileTransformer);
        }
    
        /**
         * premain
         * MANIFEST.MF.premain
         * cp target/MyTest-1.0-SNAPSHOT-jar-with-dependencies.jar ~/Documents/tool/jars/myagentpre.jar
         * MANIFEST.MF
         * java -javaagent:/Users/sunyuming/Documents/tool/jars/myagentpre.jar=sun -jar target/MyTest-1.0-SNAPSHOT-jar-with-dependencies.jar
         */
    
        /**
         * agentmain
         * MANIFEST.MF
         * cp target/MyTest-1.0-SNAPSHOT-jar-with-dependencies.jar ~/Documents/tool/jars/myagented.jar
         * java -jar ~/Documents/tool/jars/myagented.jar
         * 另一个terminal
         * MANIFEST.MF.agentmain
         * jps
         * java -Djava.ext.dirs=${JAVA_HOME}/lib -jar target/MyTest-1.0-SNAPSHOT-jar-with-dependencies.jar 47929
         */
    
        public static void main(String [] args) throws Exception {
            final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            Class vmClass = classLoader.loadClass("com.sun.tools.attach.VirtualMachine");
            Object vm = vmClass.getMethod("attach", String.class).invoke(null, args[0]);
            String path = MyTransformer.class.getProtectionDomain().getCodeSource().getLocation().getPath();
            // main与agentmain也可以分开,体现在path上,我们这边合并
            vmClass.getMethod("loadAgent", String.class, String.class).invoke(vm, path, "");
    
    // 无法通过编译,除非在pom中加入tool,即使如此,运行期也需要 -Djava.ext.dirs=${JAVA_HOME}/lib
    //        VirtualMachine vm = VirtualMachine.attach(args[0]); //正在运行的java 程序 ps id
    //        vm.loadAgent("/Users/sunyuming/work/MyTest/target/MyTest-1.0-SNAPSHOT-jar-with-dependencies.jar");
    
        }
    }
    

    被注入的jar

    Manifest-Version: 1.0
    Main-Class: agent.MyClient

    agent

    Manifest-Version: 1.0
    Main-Class: agent.MyTransformer
    Agent-Class: agent.MyTransformer
    Can-Redefine-Classes: true
    Can-Retransform-Classes: true

    premain

    Manifest-Version: 1.0
    Premain-Class: agent.MyTransformer

    2个附属:

    1)也许以后补充一个asm

    2)配置文件是否可以?

  • 相关阅读:
    P1144 最短路计数 题解 最短路应用题
    C++高精度加减乘除模板
    HDU3746 Teacher YYF 题解 KMP算法
    POJ3080 Blue Jeans 题解 KMP算法
    POJ2185 Milking Grid 题解 KMP算法
    POJ2752 Seek the Name, Seek the Fame 题解 KMP算法
    POJ2406 Power Strings 题解 KMP算法
    HDU2087 剪花布条 题解 KMP算法
    eclipse创建maven项目(详细)
    maven的作用及优势
  • 原文地址:https://www.cnblogs.com/silyvin/p/11336727.html
Copyright © 2011-2022 走看看