byte-buddy 1.9.6 简述及原理1

58 篇文章 0 订阅
31 篇文章 0 订阅

byte-buddy 1.9.6 简述及原理1

概述

核心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

 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 示例

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感觉更好)

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

方法委托方式

Class<? extends java.util.function.Function> 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();
    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值