簡單使用
import java.util.function.Consumer;
public class TestLambda {
public static void main(String[] args) {
Consumer<String> consumer = System.out::println;
consumer.accept("hello");
}
}
反編譯后字節碼
getstatic #2 <java/lang/System.out>
dup
invokestatic #3 <java/util/Objects.requireNonNull>
pop
invokedynamic #4 <accept, BootstrapMethods #0>
astore_1
aload_1
ldc #5 <hello>
invokeinterface #6 <java/util/function/Consumer.accept> count 2
return
invokedynamic是Java 7為了實現在JVM上運行動態語言而引入的一條新的虛擬機指令,它可以實現在運行期動態解析出調用點限定符所引用的方法,
然后再執行該方法,invokedynamic指令的分派邏輯是由用戶設定的引導方法決定。Lambda表達式的核心就是invokedynamic指令。
實現原理


通過debug可知,Lambda表達式最終是通過InnerClassLambdaMetafactory類來創建匿名內部類來實現的,使用ASM來創建匿名內部類

最后通過Unsafe(java提供的魔法類,可以操作底層資源)的defineAnonymousClass()方法來將字節數組轉換成Class對象,
類似於ClassLoader的loadClass()方法的功能,但這種方法生成的匿名類不顯式掛在任何ClassLoader下面,只要當該類沒有存在的實例對象、
且沒有強引用來引用該類的Class對象時,該類就會被GC回收。因此這種匿名內部類相比於Java語言層面的匿名內部類更容易回收。

通過匿名內部類的Class對象創建調用點CallSite

總結
在Lambda表達式實現中,通過invokedynamic指令調用引導方法生成調用點,在此過程中,會通過ASM動態生成字節碼,
而后利用Unsafe的defineAnonymousClass方法定義實現相應的函數式接口的匿名類,然后再實例化此匿名類,
並返回與此匿名類中函數式方法的方法句柄關聯的調用點;而后可以通過此調用點實現調用相應Lambda表達式定義邏輯的功能。