有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java byteman可以在lambda上触发规则吗?

最新的Byteman文档(4.0.16)提到了内部类,但没有提到lambdas。我有一条规则:

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

然而,它似乎从未触发。当我在没有参数的情况下运行bmsubmit时,它显示了规则,但没有提到触发器方法。我用javap检查了方法名,结果是正确的。我可以触发这个类的其他非lambda方法。我在Alpine Linux上运行OpenJDK 8

Byteman支持lambdas吗?我需要做些别的事情来触发规则吗


共 (2) 个答案

  1. # 1 楼答案

    嗯,从javap反编译中获取实现lambda主体的方法的名称是识别目标方法的一个巧妙技巧。我不知道为什么Byteman未能注入coe。你能通过Byteman JIRA实例报告这一点吗?我会调查并报告JIRA的结果。实际上,这可能是可行的

  2. # 2 楼答案

    更新:行为在版本4.0.17BYTEMAN-416)中更改,现在可以在lambda


    我能够使用一个简单的类BytemanTest和两个lambda(最后的源代码)重现这个问题

    简短回答

    字节门忽略lambda,因为编译器在字节码中将它们标记为“生成的代码

    详细回答:

    (至少在我的测试中)编译器在生成的字节码中将lambda标记为ACC_SYNTHETIC

    The Java® Virtual Machine Specification

    The ACC_SYNTHETIC flag indicates that this method was generated by a compiler and does not appear in source code, unless it is one of the methods named in §4.7.8.

    以下是javap -v -p -s -c BytemanTest.class输出的摘录:

    ...
    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”的方法

    这种行为(可能)最早是在这个ticket BYTEMAN-58(commit 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