The lambda syntax written by the developer understands the JVM level instructions generated at compile time. therefore, the actual responsibility for constructing the lambda is transferred to runtime.
To make Java less compile-time and allow JVM languages ββto link code at runtime, Java 7 introduced the new invokedynamic bytecode for the JVM and the new java.lang.invoke API package. invokedynamic facilitates the implementation of dynamic languages ββ(for the JVM) through a dynamic method call. Lambda engineers have chosen a non-dynamic approach to lambdas. Let's see what lambdas are made of:
Program:
package com.onlyfullstack; public class LambdaInternalWorking { public static void main(String[] args) { Runnable runnable = () -> System.out.println("Calling from Lambda"); } }
Let's compile the following program:
javac LambdaInternalWorking.java
Let's parse the .class file to see its contents:
javap -p LambdaInternalWorking.class Compiled from "LambdaInternalWorking.java" public class com.onlyfullstack.LambdaInternalWorking { public com.onlyfullstack.LambdaInternalWorking(); public static void main(java.lang.String[]); private static void lambda$main$0(); }
In this file we cannot see our run () method. Let's check the validity of the class file to get more clarity.
javap -verbose LambdaInternalWorking.class Classfile onlyfullstack/LambdaInternalWorking.class Last modified 30 Jan, 2019; size 1023 bytes MD5 checksum e99d1d2d0eca865f2f46960aad7216f1 Compiled from "LambdaInternalWorking.java" public class com.onlyfullstack.LambdaInternalWorking minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #7.#17 // java/lang/Object."<init>":()V #2 = InvokeDynamic #0:#22 // #0:run:()Ljava/lang/Runnable; #3 = Fieldref #23.#24 // java/lang/System.out:Ljava/io/PrintStream; #4 = String #25 // Calling from Lambda #5 = Methodref #26.#27 // java/io/PrintStream.println:(Ljava/lang/String;)V #6 = Class #28 // com/onlyfullstack/LambdaInternalWorking #7 = Class #29 // java/lang/Object #8 = Utf8 <init> #9 = Utf8 ()V #10 = Utf8 Code #11 = Utf8 LineNumberTable #12 = Utf8 main #13 = Utf8 ([Ljava/lang/String;)V #14 = Utf8 lambda$main$0 #15 = Utf8 SourceFile #16 = Utf8 LambdaInternalWorking.java #17 = NameAndType #8:#9 // "<init>":()V #18 = Utf8 BootstrapMethods #19 = MethodHandle #6:#30 // 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; #20 = MethodType #9 // ()V #21 = MethodHandle #6:#31 // invokestatic com/onlyfullstack/LambdaInternalWorking.lambda$main$0:()V #22 = NameAndType #32:#33 // run:()Ljava/lang/Runnable; #23 = Class #34 // java/lang/System #24 = NameAndType #35:#36 // out:Ljava/io/PrintStream; #25 = Utf8 Calling from Lambda #26 = Class #37 // java/io/PrintStream #27 = NameAndType #38:#39 // println:(Ljava/lang/String;)V #28 = Utf8 com/onlyfullstack/LambdaInternalWorking #29 = Utf8 java/lang/Object #30 = Methodref #40.#41 // 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; #31 = Methodref #6.#42 // com/onlyfullstack/LambdaInternalWorking.lambda$main$0:()V #32 = Utf8 run #33 = Utf8 ()Ljava/lang/Runnable; #34 = Utf8 java/lang/System #35 = Utf8 out #36 = Utf8 Ljava/io/PrintStream; #37 = Utf8 java/io/PrintStream #38 = Utf8 println #39 = Utf8 (Ljava/lang/String;)V #40 = Class #43 // java/lang/invoke/LambdaMetafactory #41 = NameAndType #44:#48 // 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; #42 = NameAndType #14:#9 // lambda$main$0:()V #43 = Utf8 java/lang/invoke/LambdaMetafactory #44 = Utf8 metafactory #45 = Class #50 // java/lang/invoke/MethodHandles$Lookup #46 = Utf8 Lookup #47 = Utf8 InnerClasses #48 = Utf8 (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; #49 = Class #51 // java/lang/invoke/MethodHandles #50 = Utf8 java/lang/invoke/MethodHandles$Lookup #51 = Utf8 java/lang/invoke/MethodHandles { public com.onlyfullstack.LambdaInternalWorking(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; 5: astore_1 6: return LineNumberTable: line 6: 0 line 7: 6 } SourceFile: "LambdaInternalWorking.java" InnerClasses: public static final #46= #45 of #49; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #19 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: #20 ()V #21 invokestatic com/onlyfullstack/LambdaInternalWorking.lambda$main$0:()V #20 ()V
We donβt need to understand the whole file, we just check the code fragment highlighted in yellow. from lines 73 - 80 contains the code written in the public method static void main (). in line number 78, the JVM makes the called dynamic call for identifier number 2, that is, line number 10. Thus, this call will actually insert the run method and execute it without creating an anonymous class.
For more information, see the links below: https://onlyfullstack.blogspot.com/2019/02/lambda-expression-tutorial-in-java-8.html
https://onlyfullstack.blogspot.com/2019/02/how-lambda-internally-works-in-java-8.html