簡體   English   中英

byteman 可以在 lambda 上觸發規則嗎?

[英]Can byteman trigger a rule on a lambda?

最新的 Byteman 文檔 (4.0.16) 提到了內部類,但沒有提到 lambda。 我有一個規則看起來像:

RULE showdir
CLASS ReportService
METHOD lambda$retrieveReport$0
AT ENTRY
IF TRUE
DO System.out.println("XXXXXXXX");
ENDRULE

但是它似乎永遠不會觸發。 當我在沒有 arguments 的情況下運行 bmsubmit 時,它顯示了規則但沒有提到觸發方法。 我用javap檢查了方法名,是正確的。 我可以觸發此 class 的其他非 lambda 方法。我在 Alpine Linux 上運行 AdoptOpenJdk 8。

Byteman 是否支持 lambda? 我是否需要執行其他操作才能觸發規則?

嗯,從 javap 反編譯中獲取實現 lambda 主體的方法的名稱是識別目標方法的巧妙技巧。 我不確定為什么 Byteman 未能注入 coe。 你能通過 Byteman JIRA 實例報告這個嗎? 我將調查並在 JIRA 上報告結果。 實際上有可能完成這項工作。

更新:該行為在4.0.17版 ( BYTEMAN-416 ) 中發生了變化,現在可以在 lambda 上觸發規則


我能夠使用帶有兩個 lambda 的簡單 class BytemanTest重現該問題(源代碼在末尾)。

簡答

Byteman忽略 lambda,因為它們在字節碼中被編譯器標記為“生成的代碼”。

長答案:

(至少在我的測試中)Lambda 在生成的字節碼中被編譯器標記為ACC_SYNTHETIC

來自Java® 虛擬機規范

ACC_SYNTHETIC 標志表示此方法由編譯器生成並且不會出現在源代碼中,除非它是 §4.7.8 中指定的方法之一。

以下是javap -v -p -s -c BytemanTest.class的 output 的摘錄:

...
private static java.lang.String lambda$doSomething$1(java.lang.String);
    descriptor: (Ljava/lang/String;)Ljava/lang/String;
    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
...
private static void lambda$main$0(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
        stack=3, locals=1, args_size=1

Byteman忽略具有標志ACC_SYNTHETIC的方法。

此行為(可能)首先在此票證BYTEMAN-58中引入(在提交ac4cbb4f中。標志測試在*Adapter類中)。

在 Byteman 的 v4.0.16 源代碼中,匹配目標方法的測試是在TransformContext#matchTargetMethod中完成的,它會忽略標記為ACC_SYNTHETIC的方法:

if ((access & (Opcodes.ACC_NATIVE|Opcodes.ACC_ABSTRACT|Opcodes.ACC_SYNTHETIC)) != 0 ||
    !targetMethodName.equals(name) ||
    (!targetDescriptor.equals("") && !TypeHelper.equalDescriptors(targetDescriptor, desc))) {
        return false;
}

我的測試 class

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class BytemanTest {
    public static void main(String[] args){
        BytemanTest bt = new BytemanTest();

        bt.doSomething(args).forEach((s) -> {
            System.out.println("Out : " + s);
        });

    }

    public List<String> doSomething(String[] args){
        return Arrays.stream(args).map( s -> s + "_test").collect(Collectors.toList());
    }
}

我的字節規則:

RULE showdir
CLASS BytemanTest
METHOD lambda$main$0
AT ENTRY
IF TRUE
DO System.out.println("lambda matched");
ENDRULE

暫無
暫無

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

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