Java仮想マシンの知識 - バイトコード

バイトコード命令

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

操作バイトコード

  操作は、CGLIB、ASM、Javassistのように直接、オープンソースのライブラリのバイトコード、などを利用することができる、彼らはプログラムを実行することができ、バイトコードのクラスは、動的に既存のクラスのバイトコードを作成または編集します。ここで、ASM CGLIBは、ライブラリーを作製するための非常に効率的かつ効果的に達成基づき、コントラスト、Javassistのがはるかに簡単;およびASMライブラリは軽量ですが、JVMや操作指示を参加させる必要性それは完全にJavaベースのAPIですが、そのパフォーマンスが悪化する前の2と比較します。

動的プロキシを使用したCGLIB

  Javaコンパイラは、実行時にプロキシクラスが、動的に生成されたプロキシクラスのバイトコードを生成し、メモリにロードされていない直後。それはJDKの動的プロキシインタフェースの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;
  }
}

  使用JDKダイナミックプロキシクラスは、インターフェイスを実装する必要があり、実際の開発にいくつかの制限があり、反射効率が非常に高くないので、操作は、バイトコード技術動的プロキシを実装するために利用することができます。春は両方の方法を達成しながら、あなたが実際の開発ではJDKの動的プロキシに基づいて、または動的プロキシCGLIBに基づいて選択することができます人気の開発フレームワークです。

githubのアドレスのCGLIB

動的プロキシCGLIBの依存関係を導入する必要性と、ASMによって達成CGLIB

<!-- 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>

これは、エージェントクラスにする必要があります

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

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

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

CGLIBインターセプタを達成する方法

// 实现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;
  }
}

テストカテゴリ

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");
  }
}

業績

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

生成されたプロキシクラス下板F

演技クラス

CGLIBは、クラスのサブクラスによって生成されるので、強化する必要があり、エージェントが動的達成するための請求方法を覆って、薬剤はCGLIBフリーできるようにインタフェースクラスを直接、しかしエージェントは、最終的なクラスはありません。

おすすめ

転載: www.linuxidc.com/Linux/2019-07/159641.htm