簡體   English   中英

如何使用ByteBuddy委托攔截bootstrap類方法

[英]How to use ByteBuddy delegation for intercepting bootstrap class method

我正在使用java agent和bytebuddy攔截FileIOStreams中的“read”和“write”方法。 要實現的功能是“在某些情況下調用原始方法,否則通過”。 因此,我需要使用方法委派來完全控制調用流,而不是使用Advice包裝它。

當@Morph不存在時,方法攔截工作正常,但是當我將@Morph添加到參數時它不起作用。 我已經測試了一些其他注釋:

添加@AllArguments,@這不會阻止委托,該方法將作為我的攔截器運行;

添加@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變形變形

要么

@AllArguments Object [] args,@ Morph Morphing變形

調用內置的寫入函數,輸出為

[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仍然表示轉換已完成? 如何為這種情況獲得正確的變形? 謝謝!

我假設你的重新轉換已經失敗了。 您是否嘗試向重新轉換過程添加偵聽器? 什么是異常:從線程“main”中的UncaughtExceptionHandler拋出的java.lang.Exception是什么意思?

我注意到的一件事是你沒有調整模塊圖。 java.base模塊將無法看到最有可能在引導加載程序的未命名模塊中加載的攔截器。 您是否嘗試在轉換中添加assureReadEdgeTo ,指向您的攔截器類?

此外,請注意, Advice允許您跳過甚至重復方法執行。 看看enter或exit方法的javadoc。 通常,在檢測引導類時,建議往往更可靠。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM