首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用ByteBuddy委托来拦截引导类方法

如何使用ByteBuddy委托来拦截引导类方法
EN

Stack Overflow用户
提问于 2019-04-09 06:45:03
回答 1查看 908关注 0票数 0

我使用java代理和字节伙伴来拦截FileIOStreams中的“读”和“写”方法。要实现的一个特性是“在某些情况下调用原始方法,否则通过”。因此,我需要使用方法委托来完全控制调用流,而不是用通知包装它。

当@Morph不存在时,该方法可以正常工作,但当我将@Morph添加到参数时,它就不能工作了。我用其他一些注释进行了测试:

添加“AllArguments”,“这不会阻止委托,该方法将作为我的拦截器运行;

添加“Morph”,“SuperCall”将阻止委托。不会抛出任何异常:原始方法将以以前的方式运行。

下面是我想实现的代码:

代码语言:javascript
复制
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的代码)

以下是我的拦截器:

代码语言:javascript
复制
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[]字节,则委托将工作并引发异常:

代码语言:javascript
复制
[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[]字节,@AllArguments Object[] args,@Morph变形

@AllArguments Object[] args,@Morph变形

内建的写函数被调用,输出是

代码语言:javascript
复制
[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之后,代理不起作用的原因是什么,但字节伙伴仍然说转换已经完成?如何得到正确的变形为这一情况?谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-11 14:25:03

我想你的改造已经失败了。您是否尝试将侦听器添加到重新转换过程中。什么是例外:线程"main“中从java.lang.Exception中抛出的UncaughtExceptionHandler意味着什么?

我注意到的一件事是,您没有调整模块图。java.base模块将无法看到您的拦截器,它很可能加载在引导加载程序的未命名模块中。您是否尝试在您的转换中添加assureReadEdgeTo,其中指向您的拦截器类?

另外,请注意,Advice确实允许您跳过甚至重复方法执行。查看enter或exit方法的javadoc。通常,当检测引导类时,通知往往更可靠。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55586623

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档