当前位置 主页 > 网站技术 > 代码类 >

    深入了解JVM字节码增强技术

    栏目:代码类 时间:2019-11-02 21:06

    这篇文章主要介绍了深入了解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 ...

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持IIS7站长之家。