Update : The behavior was changed in version 4.0.17 (BYTEMAN-416), rules can now be triggered on a lambda
I was able to reproduce the issue using a simple class BytemanTest
with two lambdas (source code at the end).
Short answer
Byteman ignores lambdas because they are marked as 'generated code' by the compiler in the bytecode.
Long answer:
(At least in my tests) Lambdas are flagged, by the compiler, as ACC_SYNTHETIC in the generated bytecode.
From 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.
The following is an excerpt from the output of 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 ignores methods that have the flag ACC_SYNTHETIC.
This behaviour was (probably) first introduced in this ticket BYTEMAN-58 (In commit ac4cbb4f. The flag test was in the *Adapter
classes).
In Byteman's source code for v4.0.16, The test to match the target method is done in TransformContext#matchTargetMethod and it ignores methods flagged as 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;
}
My test 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());
}
}
My byteman rule:
RULE showdir
CLASS BytemanTest
METHOD lambda$main$0
AT ENTRY
IF TRUE
DO System.out.println("lambda matched");
ENDRULE