微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

用Byte Buddy拦截Object.class toString方法

如何解决用Byte Buddy拦截Object.class toString方法

我使用Byte Buddy拦截了一些JDK方法,System.class和Thread.class很好,但是在java.lang.Object上不起作用。我正在JDK8上运行测试,它不会引发任何错误

final public class AgentBootstrap {
  public static void premain(String agentArgs,Instrumentation inst) throws Exception {
    try {
      new AgentBuilder.Default()
        .with(AgentBuilder.RedeFinitionStrategy.RETRANSFORMATION)
        .with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
        .with(AgentBuilder.Typestrategy.Default.REBASE)
        .enableNativeMethodPrefix("$$mynative_")
        .ignore(ElementMatchers.none())
        .with(
          new AgentBuilder.Listener.Filtering(
            new StringMatcher("java.lang.Object",StringMatcher.Mode.EQUALS_FULLY),AgentBuilder.Listener.StreamWriting.toSystemOut()))
        .type(ElementMatchers.is(Object.class))
        .transform(new Transformer() {
          @Override
          public Builder<?> transform(Builder<?> builder,TypeDescription typeDescription,ClassLoader classLoader,JavaModule module) {
            return builder.method(ElementMatchers.named("toString")).intercept(FixedValue.value("HELLO BYTE BUDDY!"));
          }
        })
        .installOn(inst);
    }
    catch (Exception e) {
      e.printstacktrace();
    }
  }
}

然后我尝试使用Javassist,转换java.lang.Object的方法成功。 任何人都可以知道为什么它不适用于Object.class吗?

解决方法

您要使用

  • disableClassFormatChanges()为了避免结构类文件更改会违反重新转换规则,
  • 建议API,以便将代码插入现有方法而无需添加新方法。
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;

import java.lang.instrument.Instrumentation;

import static net.bytebuddy.agent.builder.AgentBuilder.RedefinitionStrategy.RETRANSFORMATION;
import static net.bytebuddy.implementation.bytecode.assign.Assigner.Typing.DYNAMIC;
import static net.bytebuddy.matcher.ElementMatchers.*;

class Scratch {

  public static class ToStringAdvice {
    @Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class)
    public static boolean before() {
      // Skip original method execution (false is the default value for boolean)
      return false;
    }

    @Advice.OnMethodExit
    public static void after(@Advice.Return(readOnly = false,typing = DYNAMIC) Object returnValue) {
      // Set fixed return value
      returnValue = "HELLO BYTE BUDDY!";
    }
  }

  public static void premain(String agentArgs,Instrumentation inst) {
    new AgentBuilder.Default()
      .disableClassFormatChanges()
      .with(RETRANSFORMATION)
      .with(AgentBuilder.RedefinitionStrategy.Listener.StreamWriting.toSystemError())
      .with(AgentBuilder.Listener.StreamWriting.toSystemError().withTransformationsOnly())
      .with(AgentBuilder.InstallationListener.StreamWriting.toSystemError())
      .ignore(none())
      .type(is(Object.class))
      .transform((builder,typeDescription,classLoader,module) ->
        builder.visit(
          Advice
            .to(ToStringAdvice.class)
            .on(named("toString"))
        )
      )
      .installOn(inst);
  }

  public static void main(String[] args) throws Exception {
    Instrumentation instrumentation = ByteBuddyAgent.install();
    premain("",instrumentation);
    instrumentation.retransformClasses(Object.class);
    System.out.println(new Object());
  }

}

这有效,...

[Byte Buddy] BEFORE_INSTALL net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer@3bfdc050 on sun.instrument.InstrumentationImpl@1bce4f0a
[Byte Buddy] REDEFINE BATCH #0 [1 of 1 type(s)]
[Byte Buddy] TRANSFORM java.lang.Object [null,null,loaded=true]
[Byte Buddy] REDEFINE COMPLETE 1 batch(es) containing 1 types [0 failed batch(es)]
[Byte Buddy] INSTALL HELLO BYTE BUDDY! on HELLO BYTE BUDDY!
[Byte Buddy] TRANSFORM java.lang.Object [null,loaded=true]
HELLO BYTE BUDDY!

...但是我认为在操作JDK核心类之前,您应该三思。查看上面的日志。您是否注意到日志行中的情况

[Byte Buddy] INSTALL HELLO BYTE BUDDY! on HELLO BYTE BUDDY!

正在打印两个对象,这些对象显然使用了您刚刚建议的方法?所以要小心!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。