Why does using a method reference generate an inner class in byte code?

I wrote a simple example of using a method reference:

public class Main {
private static String identity(String param) {
    return param;
}

public static void main(String... args) {
    Function<String, String> fun = Main::identity;
    System.out.println(fun.apply("Hello"));
}}

And in the InnerClass byte code created :

InnerClasses:
 public static final #68= #67 of #71; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #35 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
  #36 (Ljava/lang/Object;)Ljava/lang/Object;....

I assumed that this innerClass is used in the lambda bootstrap method, but I do not know when jvm creates an object of this class and what information will be stored in the object of this class. Can anyone explain this to me?

+4
source share
1 answer

This is not a generated inner class, but rather an attribute InnerClassesspecified in the JVMS §4.7.6 . The specification requires that this attribute list each class (mentioned in the constant pool) that is not a member of the package.

, javac InnerClasses , . .

public class Test {
    public static void main(String[] args) {
        for (Map.Entry e : Collections.emptyMap().entrySet()) {

        }
    }
}

- Map.Entry Map:

InnerClasses:
   public static #31= #7 of #23; //Entry=class java/util/Map$Entry of class java/util/Map

JDK lambdas invokedynamic. , invokedynamic 4 :

Java Runtime , - MethodHandles.Lookup, javac InnerClasses.

+4

Source: https://habr.com/ru/post/1693121/


All Articles