[英]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 上報告結果。 實際上有可能完成這項工作。
我能夠使用帶有兩個 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;
}
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.