如何解决用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 举报,一经查实,本站将立刻删除。