• 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 ...
    

      

    
    
     
     
  • 相关阅读:
    正则表达式
    小弟新从csdn搬迁到博客园,欢迎大家关注
    做完牛腩新闻发布系统之后的收获(牛腩总结)
    ValidateRequest="false" 无效
    sql server小技巧-自动添加时间与主键自增长
    css初接触
    Spark的Rpct模块的学习
    插入排序
    选择排序
    冒泡排序
  • 原文地址:https://www.cnblogs.com/loytime/p/11749979.html
Copyright © 2020-2023  润新知