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

后端 未结 4 1951
夕颜
夕颜 2021-01-31 18:22

If you have an anonymous class like

Predicate isEmpty = new Predicate() {
    public boolean test(String t) {
        return t.isEmpt         


        
相关标签:
4条回答
  • 2021-01-31 18:56

    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.

    0 讨论(0)
  • 2021-01-31 19:10

    I found another way: by patching the InnerClassLambdaMetafactory it is possible to add an annotation to the lambda classes which points to the implementation method. This is possible at runtime by loading an agent and retransforming the metafactory. See my Blog for details.

    0 讨论(0)
  • 2021-01-31 19:13

    The simple answer is: You can't. There is a related answer of Brian Goetz on this matter. For implementing lambda expressions, javac creates an INVOKEDYNAMIC instruction which delegates the invocation to the LambdaMetafactory's bootstrap method. For the OpenJDK, this bootstrap method is then creating an implementation of the required interface at runtime using ASM.

    Within the test method, the retreived instance tester is of this ASM-generated class such that you have no class file to read for finding out which method the Predicate represents. In the general case, the exact decision of how to map lambda expressions to interface implementations is left to the runtime environment what makes your problem even harder. The only way to find out which method a lambda expression represents is to read the byte code of its creation, i.e. interpreting the main method, for your example.

    0 讨论(0)
  • 2021-01-31 19:16

    After all, I found a way of getting hold of a lambda expression's class file that is rather reliable (but of course still relies on implementation details.) For an experimental implementation, I am now using a Java agent which allows for the retransformation of classes but which is itself implemented as a no-op, I am only interested in the binary array that is handed as an argument.

    After getting hold of an Instrumentation instance via the registered Java agent, one registers a ClassFileTransformer which is then notified over the binary representation once one retransforms lambdaInstance.getClass(). This is of course a rather hacky solution and might break once the internal implementation of lambdas is changed in the future.

    Unfortunately, I did not find any documentation on how an agent is supposed to behave with class retransformation of a lambda expression's synthetic class on a standards-compatible JVM.

    0 讨论(0)
提交回复
热议问题