美文网首页
ASM(动态增强)

ASM(动态增强)

作者: 火火说技术 | 来源:发表于2018-05-08 13:25 被阅读0次

ASM(动态)

前面那篇是静态修改字节码的方式,这种方式只是一种demo,方便初学者进行学习基本的API操作,真正在线上环境有作用的是动态的去修改字节码。

例如一个进程正在运行着,这个时候我们需要在业务无感知的情况下进行打印日志,或者计算接口的操作时间这种操作,这个时候我们就需要动态的去操作JVM中的字节码文件了

动态操作字节码

动态操作字节码的方式,其实还是主要使用agentmain,在javaagent的类attch到jvm上面的时候会调用这个方法执行内部的代码逻辑。

如何使用

首先我们需要有一个agent,这个agent实现了agentmain的方法,并且改写对应类的字节码文件。DynamicPreMainAddTimeStatAgent

public class DynamicPreMainAddTimeStatAgent {


    public static void agentmain(String agentArgs, Instrumentation inst) throws Exception {
        System.out.println("Agent Main called");
        System.out.println("agentArgs:" + agentArgs);
        inst.addTransformer(new ClassFileTransformer() {
            public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
                System.out.println("load transform");

                if (className.equals("com/wsqandgy/asm/dynamic/Account")) {
                    System.out.println("meet com/wsqandgy/asm/dynamic/Account ");
                    /** classfileBuffer */
                    ClassReader classReader = new ClassReader(classfileBuffer);
                    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
                    TimeStatClassAdapter timeStatClassAdapter = new TimeStatClassAdapter(cw);
                    classReader.accept(timeStatClassAdapter, ClassReader.SKIP_DEBUG);
                    byte[] data = cw.toByteArray();
                    return data;
                } else {
                    System.out.println("load class:" + className);
                    System.out.println("new !");
                    return classfileBuffer;
                }
            }
        },true);
        System.out.println(Account.class.getClassLoader());
        inst.retransformClasses(Account.class);
    }
}

在上述操作中使用了TimeStatClassAdapter这个Class修改适配器和TimeStatMethodAdapter修改适配器。

增加TimeStat的方法,提供打印运行时间的方法。

public class TimeStat {
    static ThreadLocal<Long> t = new ThreadLocal<Long>();


    public static void start() {
        t.set(System.currentTimeMillis());
    }

    public static void end() {
        long time = System.currentTimeMillis();
        System.out.print(Thread.currentThread().getStackTrace()[2] + " spend:");
        System.out.println(time - t.get());
    }
}

针对上面的内容创建MANIFEST.MF文件,并且进行打成jar包。

Manifest-Version: 1.0
Agent-Class: com.wsqandgy.asm.dynamic.DynamicPreMainAddTimeStatAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true

以上就是全部改写字节码文件的类和agentmain对应方法的类文件了。众所周知,我们需要对JVM进行注入就需要获取到全部的JVM运行信息,Java提供了一个方法可以获取到运行的JVM的相关信息。List<VirtualMachineDescriptor> list = VirtualMachine.list();

我们通过以上的方法获取到对应的JVM运行实例,进行attch操作。

public class AttachToolMain {
    public static void main(String[] args) throws Exception {
        List<VirtualMachineDescriptor> list = VirtualMachine.list();
        for (VirtualMachineDescriptor machineDescriptor : list) {
            if (machineDescriptor.displayName().equals("com.wsqandgy.asm.dynamic.RunLoopAccountMain")) {
                VirtualMachine virtualMachine = VirtualMachine.attach(machineDescriptor.id());
                System.out.println(new File("/Users/gongyan/Documents/home_code/tools/classes/artifacts/dynamicTimeAgent/dynamicTimeAgent.jar").exists());
                virtualMachine.loadAgent("/Users/gongyan/Documents/home_code/tools/classes/artifacts/dynamicTimeAgent/dynamicTimeAgent.jar","argument for agent");
                System.out.println("attach ok!");
                virtualMachine.detach(); // 派遣操作,意思为生效
            }
        }
    }
}

运行效果:

before

当我们运行AttachToolMain后,字节码重新生成已经增加了对应的响应时间了。

after

相关文章

  • ASM(动态增强)

    ASM(动态) 前面那篇是静态修改字节码的方式,这种方式只是一种demo,方便初学者进行学习基本的API操作,真正...

  • JAVA中ASM是什么?

    什么是 ASM ? ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可...

  • 深入开源框架底层之ASM

    什么是 ASM ? ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可...

  • 简单看看ASM框架

    什么是ASM ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接...

  • 43 AOP(面向切面编程)-ASM-2

    1. ASM 介绍 ASM 是一个 Java 字节码操作框架,它能用来动态生成类或者增强既有类的功能。ASM 可以...

  • [转载]AOP 的利器:ASM 3.0 介绍

    引言 什么是 ASM ? ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。AS...

  • AOP之利器:ASM介绍

    什么是ASM? ASM是一个字节码操控框架。它能被用来动态生成类,或者增强既有类的功能。ASM可以直接产生二进制c...

  • 动态代理-Cglib实现原理

    动态代理-Cglib实现原理 Cglib提供了一种运行时动态增强类的功能。基于ASM在运行时动态创建class,暴...

  • Android ASM字节码插桩(上)

    一、ASM简介ASM是一个字节码操作框架,可用来动态生成字节码或者对现有的类进行增强。ASM可以直接生成二进制的c...

  • ASM 无痕埋点

    ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 c...

网友评论

      本文标题:ASM(动态增强)

      本文链接:https://www.haomeiwen.com/subject/hfnirftx.html