如何使用ByteBuddy委托拦截bootstrapclass方法
How to use ByteBuddy delegation for intercepting bootstrap class method
我正在使用 java 代理和 bytebuddy 拦截 FileIOStreams 中的 "read" 和 "write" 方法。要实现的功能是 "to call the original methods under certain circumstances, else pass"。因此,我需要使用方法委托来完全控制调用流程,而不是用 Advice 包装它。
当@Morph 不存在时方法拦截工作正常,但当我将@Morph 添加到参数时它不起作用。我已经测试了一些其他注释:
添加@AllArguments,@This不会阻塞委托,方法会运行作为我的拦截器;
添加@Morph、@SuperCall 将阻止委托。不会抛出异常:原始方法将 运行 和以前一样。
这是我要实现的代码:
public static void mountAgent(Instrumentation inst) {
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
.with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
.with(AgentBuilder.TypeStrategy.Default.REDEFINE)
.ignore(new AgentBuilder.RawMatcher.ForElementMatchers(nameStartsWith("net.bytebuddy.").or(isSynthetic()), any(), any()))
.with(new AgentBuilder.Listener.Filtering(
new StringMatcher("java.io.FileInputStream", StringMatcher.Mode.EQUALS_FULLY)
.or(new StringMatcher("java.io.FileOutputStream", StringMatcher.Mode.EQUALS_FULLY)),
AgentBuilder.Listener.StreamWriting.toSystemOut()))
.type(named("java.io.FileOutputStream"))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule module) {
return builder.method(named("write").and(not(isNative())).and(takesArgument(0, byte[].class)))
.intercept(MethodDelegation
.withDefaultConfiguration()
.withBinders(Morph.Binder.install(Morphing.class))
.to(WriteInterceptor.class));
}})
.installOn(inst);
}
(将拦截器附加到 BootstrapClassLoaderSearch 的代码被跳过)
下面是我的拦截器:
public interface Morphing<T> {
T Object invoke(Object[] agrs);
}
@SuppressWarnings("unused")
public static class WriteInterceptor {
@RuntimeType
public static void write(
//change the input here
byte[] bytes,
@AllArguments Object[] args,
@Morph Morphing<Void> morphing
) throws Exception {
if (true) {
morphing.invoke(args);
}
else {
// do something
throw new Exception();
}
}
}
如果拦截函数的输入为空或者只有byte[]字节,委托会起作用并抛出异常:
[Byte Buddy] IGNORE java.io.FileInputStream [null, module java.base, loaded=true]
[Byte Buddy] COMPLETE java.io.FileInputStream [null, module java.base, loaded=true]
[Byte Buddy] DISCOVERY java.io.FileOutputStream [null, module java.base, loaded=true]
[Byte Buddy] TRANSFORM java.io.FileOutputStream [null, module java.base, loaded=true]
[Byte Buddy] COMPLETE java.io.FileOutputStream [null, module java.base, loaded=true]
Exception: java.lang.Exception thrown from the UncaughtExceptionHandler in thread "main"
如果输入是
byte[] bytes, @AllArguments Object[] args, @Morph Morphing morphing
或
@AllArguments Object[] args, @Morph Morphing morphing
调用内置的write函数,输出为
[Byte Buddy] IGNORE java.io.FileInputStream [null, module java.base, loaded=true]
[Byte Buddy] COMPLETE java.io.FileInputStream [null, module java.base, loaded=true]
[Byte Buddy] DISCOVERY java.io.FileOutputStream [null, module java.base, loaded=true]
[Byte Buddy] TRANSFORM java.io.FileOutputStream [null, module java.base, loaded=true]
[Byte Buddy] COMPLETE java.io.FileOutputStream [null, module java.base, loaded=true]
添加@Morph后委托不起作用,但bytebuddy仍然说transform完成是什么原因?如何为这种情况获得正确的变形?谢谢!
我假设您的重新转换已经失败了。您是否尝试将侦听器添加到重新转换过程中。 Exception: java.lang.Exception 从线程 "main" 中的 UncaughtExceptionHandler 抛出是什么意思?
我注意到的一件事是您没有调整模块图。 java.base 模块将无法看到您的拦截器,它很可能被加载到 bootstrap 加载器的未命名模块中。您是否尝试在指向拦截器 class 的转换中添加 assureReadEdgeTo?
另外,请注意 Advice
确实允许您跳过甚至重复方法执行。查看 enter 或 exit 方法的 javadoc。通常,在检测时 bootstrap classes 建议往往更可靠。
我正在使用 java 代理和 bytebuddy 拦截 FileIOStreams 中的 "read" 和 "write" 方法。要实现的功能是 "to call the original methods under certain circumstances, else pass"。因此,我需要使用方法委托来完全控制调用流程,而不是用 Advice 包装它。
当@Morph 不存在时方法拦截工作正常,但当我将@Morph 添加到参数时它不起作用。我已经测试了一些其他注释:
添加@AllArguments,@This不会阻塞委托,方法会运行作为我的拦截器;
添加@Morph、@SuperCall 将阻止委托。不会抛出异常:原始方法将 运行 和以前一样。
这是我要实现的代码:
public static void mountAgent(Instrumentation inst) {
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
.with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
.with(AgentBuilder.TypeStrategy.Default.REDEFINE)
.ignore(new AgentBuilder.RawMatcher.ForElementMatchers(nameStartsWith("net.bytebuddy.").or(isSynthetic()), any(), any()))
.with(new AgentBuilder.Listener.Filtering(
new StringMatcher("java.io.FileInputStream", StringMatcher.Mode.EQUALS_FULLY)
.or(new StringMatcher("java.io.FileOutputStream", StringMatcher.Mode.EQUALS_FULLY)),
AgentBuilder.Listener.StreamWriting.toSystemOut()))
.type(named("java.io.FileOutputStream"))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule module) {
return builder.method(named("write").and(not(isNative())).and(takesArgument(0, byte[].class)))
.intercept(MethodDelegation
.withDefaultConfiguration()
.withBinders(Morph.Binder.install(Morphing.class))
.to(WriteInterceptor.class));
}})
.installOn(inst);
}
(将拦截器附加到 BootstrapClassLoaderSearch 的代码被跳过)
下面是我的拦截器:
public interface Morphing<T> {
T Object invoke(Object[] agrs);
}
@SuppressWarnings("unused")
public static class WriteInterceptor {
@RuntimeType
public static void write(
//change the input here
byte[] bytes,
@AllArguments Object[] args,
@Morph Morphing<Void> morphing
) throws Exception {
if (true) {
morphing.invoke(args);
}
else {
// do something
throw new Exception();
}
}
}
如果拦截函数的输入为空或者只有byte[]字节,委托会起作用并抛出异常:
[Byte Buddy] IGNORE java.io.FileInputStream [null, module java.base, loaded=true]
[Byte Buddy] COMPLETE java.io.FileInputStream [null, module java.base, loaded=true]
[Byte Buddy] DISCOVERY java.io.FileOutputStream [null, module java.base, loaded=true]
[Byte Buddy] TRANSFORM java.io.FileOutputStream [null, module java.base, loaded=true]
[Byte Buddy] COMPLETE java.io.FileOutputStream [null, module java.base, loaded=true]
Exception: java.lang.Exception thrown from the UncaughtExceptionHandler in thread "main"
如果输入是
byte[] bytes, @AllArguments Object[] args, @Morph Morphing morphing
或
@AllArguments Object[] args, @Morph Morphing morphing
调用内置的write函数,输出为
[Byte Buddy] IGNORE java.io.FileInputStream [null, module java.base, loaded=true]
[Byte Buddy] COMPLETE java.io.FileInputStream [null, module java.base, loaded=true]
[Byte Buddy] DISCOVERY java.io.FileOutputStream [null, module java.base, loaded=true]
[Byte Buddy] TRANSFORM java.io.FileOutputStream [null, module java.base, loaded=true]
[Byte Buddy] COMPLETE java.io.FileOutputStream [null, module java.base, loaded=true]
添加@Morph后委托不起作用,但bytebuddy仍然说transform完成是什么原因?如何为这种情况获得正确的变形?谢谢!
我假设您的重新转换已经失败了。您是否尝试将侦听器添加到重新转换过程中。 Exception: java.lang.Exception 从线程 "main" 中的 UncaughtExceptionHandler 抛出是什么意思?
我注意到的一件事是您没有调整模块图。 java.base 模块将无法看到您的拦截器,它很可能被加载到 bootstrap 加载器的未命名模块中。您是否尝试在指向拦截器 class 的转换中添加 assureReadEdgeTo?
另外,请注意 Advice
确实允许您跳过甚至重复方法执行。查看 enter 或 exit 方法的 javadoc。通常,在检测时 bootstrap classes 建议往往更可靠。