Can you inspect the byte code of a Java 8 lambda at runtime?

bytecode, java, java-8, lambda

Solution

If you just want to SEE the bytecode:

javap -c -p -v classfile
      ^disassemble
         ^private methods
            ^verbose, including constant pool and bootstrap methods attribute

But if you want to try to do this at runtime, you're pretty much out of luck (by design, we don't have anything like Expression Trees), as the other answer suggests.

Problem

If you have an anonymous class like ``` Predicate<String> isEmpty = new Predicate<String>() { public boolean test(String t) { return t.isEmpty(); } }; ``` A library which is passed the reference to `isEmpty` can inspect the byte code to see what it does and possibly manipulate it. Is there a way you can do this for lambdas? ``` Predicate<String> isEmpty = String::isEmpty; ``` e.g Say have this code and byte code ``` public class Main { public static void test(Predicate<String> tester) { System.out.println("tester.getClass()= " + tester.getClass()); System.out.println("tester.getClass().getClassLoader()="+ tester.getClass().getClassLoader()); } public static void main(String... args) { Predicate<String> isEmpty = String::isEmpty; test(isEmpty); } } $ javap -cp . -c -private Main.class Compiled from "Main.java" public class Main { public Main(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void test(java.util.function.Predicate<java.lang.String>); Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #3 // class java/lang/StringBuilder 6: dup 7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V 10: ldc #5 // String tester.getClass()= 12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 15: aload_0 16: invokevirtual #7 // Method java/lang/Object.getClass:()Ljava/lang/Class; 19: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 22: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 25: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 28: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 31: new #3 // class java/lang/StringBuilder 34: dup 35: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V 38: ldc #11 // String tester.getClass().getClassLoader()= 40: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 43: aload_0 44: invokevirtual #7 // Method java/lang/Object.getClass:()Ljava/lang/Class; 47: invokevirtual #12 // Method java/lang/Class.getClassLoader:()Ljava/lang/ClassLoader; 50: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 53: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 56: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 59: return public static void main(java.lang.String...); Code: 0: invokedynamic #13, 0 // InvokeDynamic #0:test:()Ljava/util/function/Predicate; 5: astore_1 6: aload_1 7: invokestatic #14 // Method test:(Ljava/util/function/Predicate;)V 10: return } ``` With a reference to `tester` in `test` how do I find which method is called?

Original source

Related problems