byte-buddy 1.9.6 简述及原理1

byte-buddy 1.9.6 简述及原理1

概述

  • 参考
    • https://github.com/raphw/byte-buddy
    • https://github.com/diguage/byte-buddy-tutorial
    • https://blog.csdn.net/qyongkang/article/details/7799603 -javaagent参数使用

核心Code

  • ByteBuddy
    • 流式api方式的入口类
    • 提供Subclassing/Redefining/Rebasing方式改写字节码
    • 所有的操作依赖DynamicType.Builder进行,创建不可变的对象
  • ElementMatchers(ElementMatcher)
    • 提供一系列的元素匹配的工具类(named/any/nameEndsWith等等)
    • ElementMatcher(提供对类型、方法、字段、注解进行matches的方式,类似于Predicate)
      • Junction对多个ElementMatcher进行了and/or操作
  • Implementation(用于提供动态方法的实现)
    • FixedValue(方法调用返回固定值)
    • MethodDelegation(方法调用委托,支持以下两种方式)
      • Class的static方法调用
      • object的instance method方法调用
  • DynamicType(动态类型,所有字节码操作的开始,非常值得关注)
    • Unloaded(动态创建的字节码还未加载进入到虚拟机,需要类加载器进行加载)
    • Loaded(已加载到jvm中后,解析出Class表示)
    • Default(DynamicType的默认实现,完成相关实际操作)
  • Builder(用于创建DynamicType,相关接口以及实现后续待详解)
    • MethodDefinition
    • FieldDefinition
    • AbstractBase
  • AgentBuilder(java agent的操作入口,后续详解)
  • Transformer(对实例进行转换操作)

示例(https://github.com/undergrowthlinear/byte-buddy-test)

HelloWorld

  • 完整示例代码: https://github.com/undergrowthlinear/byte-buddy-test/blob/master/src/test/java/com/undergrowth/ByteBuddyHelloWorldTest.java
  • 核心解释
 Class dynamicType = new ByteBuddy()
            .subclass(Object.class)
            .method(ElementMatchers.named("toString"))
            .intercept(FixedValue.value("Hello World!"))
            .make()
            .load(getClass().getClassLoader())
            .getLoaded();
        String str = dynamicType.newInstance().toString();
        System.out.println(str);
        Assert.assertEquals("toString方法改写错误", str, "Hello World!");
  • dynamicType继承Object,重写toString方法,将该方法的返回值固定为Hello World!,利用当前类的类加载器,将字节码加载到虚拟机中,形成Class字节码表示

Agent 示例

  • 完整示例代码:https://github.com/undergrowthlinear/byte-buddy-test/tree/master/src/main/java/com/undergrowth/agent
  • 1.编写agnet核心
public static void premain(String arguments, Instrumentation instrumentation) {
        new AgentBuilder.Default()
            .type(ElementMatchers.isAnnotatedWith(ToString.class))
            .transform(new AgentBuilder.Transformer() {
                @Override
                public Builder transform(Builder builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
                    return builder.method(named("toString"))
                        .intercept(FixedValue.value("transformed"));
                }
            }).installOn(instrumentation);
    }
  • 拦截被ToString注解标注的类,对其toString方法进行拦截后,返回固定值
  • 2.添加maven-shade-plugin插件,添加premain
  • 3.com.undergrowth.AgentToStringMain#main 启动 可通过是否添加 -javaagent参数 查看代理机制有无生效

Agent 类似于切面示例(通过aspectj感觉更好)

  • 完整示例代码:https://github.com/undergrowthlinear/byte-buddy-test/tree/master/src/main/java/com/undergrowth/time
  • 1.编写agnet核心
public static void premain(String arguments,
        Instrumentation instrumentation) {
        new AgentBuilder.Default()
            .type(ElementMatchers.nameEndsWith("Timed"))
            .transform((builder, type, classLoader, module) ->
                builder.method(ElementMatchers.any())
                    .intercept(MethodDelegation.to(TimingInterceptor.class))
            ).installOn(instrumentation);
    }
  • 拦截后缀名为Timed的类,对其任意方法进行拦截后,打印方法调用时间
  • 2.添加maven-shade-plugin插件,添加premain
  • 3.com.undergrowth.time.TimingInterceptorMain#main 启动 可通过是否添加 -javaagent参数 查看代理机制有无生效
hello world
public void com.undergrowth.time.AgentInterceptorTimed.hello() took 1
hello world helloSleep
public void com.undergrowth.time.AgentInterceptorTimed.helloSleep() throws java.lang.InterruptedException took 1453

方法委托方式

  • 完整示例代码:https://github.com/undergrowthlinear/byte-buddy-test/blob/master/src/test/java/com/undergrowth/MethodInterceptorTest.java
  • com.undergrowth.MethodInterceptorTest#interceptorSimpleTest
    • 简单模式(将Function的apply调用委托给javabean的方法调用)
Class dynamicType = new ByteBuddy()
            .subclass(java.util.function.Function.class)
            .method(ElementMatchers.named("apply"))
            .intercept(MethodDelegation.to(new GreetingInterceptorSimple()))
            .make()
            .load(getClass().getClassLoader())
            .getLoaded();
  • com.undergrowth.MethodInterceptorTest#interceptorComplexTest
  • com.undergrowth.MethodInterceptorTest#interceptorComplex2Test
    • 复杂模式(兼容所有情况/获取到原有调用方法以及所有的方法调用参数)
@RuntimeType
    public Object intercept(@AllArguments Object[] allArguments,
        @Origin Method method) {
        // intercept any method of any signature
        System.out.println("called:" + method.getName());
        if (allArguments != null && allArguments.length > 0) {
            return "Hello from " + allArguments[0];
        }
        return "Hello from " + method.getName();
    }

你可能感兴趣的:(java,bigdata,分布式,java_第三方,底层)