Java virtual machine knowledge - bytecode

Bytecode instruction

do {
  自动计算PC寄存器以及从PC寄存器的位置取出操作码;
if (存在操作数) 取出操作数;
  执行操作码所定义的操作;
} while (处理下一次循环);

Operation bytecode

  Operation may be utilized directly open source library byte code, such as CGLib, ASM, Javassist the like, they can run the program, the bytecode classes dynamically create or edit existing class bytecode. Wherein, based ASM CGLib achieved, a highly efficient and effective for generating libraries; and ASM library is a lightweight, but the need to involve the JVM and operation instructions; contrast, Javassist much simpler, It is completely Java-based API, but its performance compared to the previous two to be worse.

CGLib using dynamic proxy

  Immediately after the Java compiler does not generate proxy classes, but dynamically generated proxy class bytecode at runtime, and loaded into memory. Since it can achieve by implementing the JDK dynamic proxy interface InvocationHandler.

// 示例:JDK实现动态代理
public class ProxyHandler implements InvocationHandler {
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("Start");
    Object o = method.invoke(this, args);
    System.out.println("End");
    return o;
  }
}

  Use JDK dynamic proxy class must implement an interface, there are some limitations in the actual development, the reflection efficiency is not very high, and therefore the operation may be utilized to implement the bytecode art dynamic proxy. Spring is a popular development framework while achieving both ways, you can choose based on JDK dynamic proxy in the actual development, or based on a dynamic proxy CGLib.

CGLib of github address

CGLib achieved by the need to introduce dynamic proxy CGLib dependencies and asm

<!-- cglib -->
<dependency>
  <groupId>cglib</groupId>
  <artifactId>cglib</artifactId>
  <version>3.2.12</version>
</dependency>
<!-- asm -->
<dependency>
  <groupId>asm</groupId>
  <artifactId>asm</artifactId>
  <version>3.3.1</version>
</dependency>

It needs to be the agent class

// 需要被代理的类
public class HelloCGLib {

  public HelloCGLib() {
    System.out.println("HelloCGLib构造器");
  }

  public void sayHello(String name) {
    System.out.println("HelloCGLib:" + name);
  }
}

CGLib way to achieve interceptor

// 实现CGLib的方法拦截器
public class ProxyInterceptor implements MethodInterceptor {

  /**
   * @param o           cglib生成的代理对象
   * @param method      被代理对象方法
   * @param objects     方法入参
   * @param methodProxy 代理方法
   */
  @Override
  public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    System.out.println("======前置通知======");
    Object object = methodProxy.invokeSuper(o, objects);
    System.out.println("======后者通知======");
    return object;
  }
}

Test category

public class Test {
  public static void main(String[] args) {
    // 代理类class文件存入本地磁盘方便我们反编译查看源码
    System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "F:\\");
    // CGLIB 增强类
    Enhancer enhancer = new Enhancer();
    // 设置增强类对象的父类
    enhancer.setSuperclass(HelloCGLib.class);
    // 设置增强类的回调类
    enhancer.setCallback(new ProxyInterceptor());
    // 创建代理对象
    HelloCGLib proxy = (HelloCGLib) enhancer.create();
    // 通过代理对象调用目标方法
    proxy.sayHello("hehe");
  }
}

operation result

HelloCGLib构造器
======前置通知======
HelloCGLib:hehe
======后者通知======

The generated proxy class lower plate F

Acting Class

Since CGlib is generated by a subclass of the class needs to be enhanced, and covers a method wherein the agent to achieve dynamic, so the agent may CGlib-free interface classes directly, but the agent is not a final class.

Guess you like

Origin www.linuxidc.com/Linux/2019-07/159641.htm