JVM字节码增强

Posted loytime

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM字节码增强相关的知识,希望对你有一定的参考价值。

JVM——字节码增强技术简介
    Java字节码增强指的是在Java字节码生成之后,对其进行修改,增强其功能,这种方式相当于对应用程序的二进制文件进行修改。Java字节码增强主要是为了减少冗余代码,提高性能等。
    实现字节码增强的主要步骤为:
 
  1、修改字节码
   在内存中获取到原来的字节码,然后通过一些工具(如 ASM,Javaasist)来修改它的byte[]数组,得到一个新的byte数组。
 
  2、使修改后的字节码生效
    有两种方法:
   1) 自定义ClassLoader来加载修改后的字节码;
   2)替换掉原来的字节码:在JVM加载用户的Class时,拦截,返回修改后的字节码;或者在运行时,使用Instrumentation.redefineClasses方法来替换掉原来的字节码;
 
3. 两种实现机制:   
(1) 通过创建原始类的一个子类(动态创建的类继承原来的类)。子类名以原始类名为前缀,以避免重名。Spring AOP 使用的就是这种   
(2) 直接修改原始类的字节码。类的跟踪过程中使用
 
4. 实现字节码增强要执行两个步骤:   
(1) 在内存中获取到原始的字节码, 然后通过一些开源的API 来修改它的byte[] 数组,得到一个新的byte[] 数组。 
(2) 将新的byte[] 数组加载到PermGen 区(即加载新的byte[] 数组或替换原始类的字节码)。
 
接口 BCInterface
public interface BCInterface {
    void enhancement();
}

  实现类 BCEnhancement.java

public class BCEnhancement implements BCInterface{

    public void enhancement() {
        System.out.println("hello enhancement");
    }
    
}

  

LogProxy.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class LogProxy implements InvocationHandler {

    private Object object;

    public Object getProxyObject(Object o){
        object=o;
        try{
            return Proxy.newProxyInstance(this.getClass().getClassLoader(),o.getClass().getInterfaces(),this);
        }catch (IllegalArgumentException e){
            throw new RuntimeException(e);
        }

    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before invoke ...");
        Object result= method.invoke(object,args);
        System.out.println("after invoke ...");
        return result;
    }

}

  测试类 Test.java

public class Test {

    public static void main(String[] args) {
        LogProxy logProxy = new LogProxy();
        System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        BCInterface byteCodeEn = (BCInterface) logProxy.getProxyObject(new BCEnhancement());
        byteCodeEn.enhancement();

    }

}

  输出:

before invoke ...
hello enhancement
after invoke ...

  


 
 

以上是关于JVM字节码增强的主要内容,如果未能解决你的问题,请参考以下文章

字节码增强技术探索

字节码增强

字节码增强之Javassist

字节码增强之Javassist

字节码增强之Javassist

深度详解JVM类字节码