Upgrade to Pro — share decks privately, control downloads, hide ads and more …

今こそ、ラムダ式を考える - ラムダ式はどうやって動くのか

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

今こそ、ラムダ式を考える - ラムダ式はどうやって動くのか

Burikaigi ブリ会議 2024
発表資料

Java, Java SE, Project Lambda, Lambda Expression, ラムダ式
Bytecode, バイトコード, javap, InvokeDynamic, indy

Yuichi.Sakuraba

January 19, 2024

Transcript

21 slides
  1. ラムダ式 = (無名)関数 ≠ 言語仕様的には Java では、関数は 1st Class Citizen

    ではない 関数型は提供されていない ラムダ式 : 型システムを変更することなく 現行の型システムの範囲内で 関数のようなものを表したもの
  2. ラムダ式 = (無名)関数 ≠ 言語仕様的には I think getting worked up

    over whether Lambdas as expressed in Java SE 8 are "real" closures or not is a pretty unconstructive activity Project Lambda from the Inside. An Interview with Brian Goetz Victor Grazi, InfoQ 2013
  3. Function<Integer, Integer> func = new Function<>() { public Integer apply(Integer

    x) { return x+1; }}; 0: new #7 // class IncAnon$1 3: dup 4: invokespecial #9 // Method IncAnon$1."<init>":()V 7: astore_1 Function<Integer, Integer> func = x -> x+1; 0: invokedynamic #7,0 // InvokeDynamic #0:apply:()Ljava/util/function/Function; 5: astore_1
  4. InvokeDynamic 導入の背景 2000年代 JVM言語の興隆 JRuby Scala Groovy Jython Rhino (JavaScript)

    et al. 動的型付け言語をJVMで実装しにくい var x = ...; var y = ...; add(x, y); int add(int x, int y) {...} String add(String x, String y) {...} どちらをコールするかは 実行時にならないと決まらない InvokeDynamic
  5. ラムダ式の実行 IncLambda.java IncLambda.class コンパイル ラムダ式のメソッドボディを static メソッド化して追加 ラムダ式実行 bootstrap 初回

    関数型インタフェース実装クラスを動的生成 メソッドはコンパイル時に生成した static メソッドをコール 動的生成クラスをインスタンシエーションする CallSite を生成 CallSite からインスタンシエーション実行 2回目以降
  6. > more IncLambda.java import java.util.function.Function; public class IncLambda { public

    static void main(String... args) { Function<Integer, Integer> func = x -> x+1; System.out.println(func.apply(0)); } } > more IncLambda.java import java.util.function.Function; public class IncLambda { public static void main(String... args) { Function<Integer, Integer> func = x -> x+1; System.out.println(func.apply(0)); } } > javac IncLambda.java > > more IncLambda.java import java.util.function.Function; public class IncLambda { public static void main(String... args) { Function<Integer, Integer> func = x -> x+1; System.out.println(func.apply(0)); } } > javac IncLambda.java > javap -private IncLambda Compiled from "IncLambda.java" public class IncLambda { public IncLambda(); public static void main(java.lang.String...); private static java.lang.Integer lambda$main$0(java.lang.Integer); } javap クラスファイル解析ツール
  7. > more IncLambda.java import java.util.function.Function; public class IncLambda { public

    static void main(String... args) { Function<Integer, Integer> func = x -> x+1; System.out.println(func.apply(0)); } } > more IncLambda.java import java.util.function.Function; public class IncLambda { public static void main(String... args) { Function<Integer, Integer> func = x -> x+1; System.out.println(func.apply(0)); } } > javac IncLambda.java > > more IncLambda.java import java.util.function.Function; public class IncLambda { public static void main(String... args) { Function<Integer, Integer> func = x -> x+1; System.out.println(func.apply(0)); } } > javac IncLambda.java > javap -private IncLambda Compiled from "IncLambda.java" public class IncLambda { public IncLambda(); public static void main(java.lang.String...); private static java.lang.Integer lambda$main$0(java.lang.Integer); }
  8. > javap -c -private IncLambda Compiled from "IncLambda.java" public class

    IncLambda { <<লུ>> private static java.lang.Integer lambda$main$0(java.lang.Integer); Code: 0: aload_0 1: invokevirtual #34 // Method java/lang/Integer.intValue:()I 4: iconst_1 5: iadd 6: invokestatic #17 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 9: areturn } -c バイトコード出力 private static Integer lambda$main$0(Integer x) { int xx = x.intValue(); xx = xx + 1; return Integer.valueOf(xx); }
  9. > javap -v -private IncLambda Compiled from "IncLambda.java" public class

    IncLambda { <<লུ>> BootstrapMethods: 0: #54 REF_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: #49 (Ljava/lang/Object;)Ljava/lang/Object; #50 REF_invokeStatic IncLambda.lambda$main$0: (Ljava/lang/Integer;)Ljava/lang/Integer; #53 (Ljava/lang/Integer;)Ljava/lang/Integer; -v 詳細情報出力 > javap -v -private IncLambda Compiled from "IncLambda.java" public class IncLambda { <<লུ>> BootstrapMethods: 0: #54 REF_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: #49 (Ljava/lang/Object;)Ljava/lang/Object; #50 REF_invokeStatic IncLambda.lambda$main$0: (Ljava/lang/Integer;)Ljava/lang/Integer; #53 (Ljava/lang/Integer;)Ljava/lang/Integer; ラムダ式用の bootstrap 生成したメソッドを bootstrap の引数にする
  10. > java -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles=true IncLambda 1 > 動的生成したクラスを ファイル出力するオプション > java

    -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles=true IncLambda 1 > ls IncLambda.class IncLambda.java DUMP_LAMBDA_PROXY_CLASS_FILES > cd DUMP_LAMBDA_PROXY_CLASS_FILES > ls IncLambda$$Lambda.0x00000165e0000a00.class > > java -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles=true IncLambda 1 > ls IncLambda.class IncLambda.java DUMP_LAMBDA_PROXY_CLASS_FILES > cd DUMP_LAMBDA_PROXY_CLASS_FILES > ls IncLambda$$Lambda.0x00000165e0000a00.class > javap -c IncLambda$$Lambda.0x00000165e0000a00.class final class IncLambda$$Lambda implements java.util.function.Function { public java.lang.Object apply(java.lang.Object); Code: 0: aload_1 1: checkcast #14 // class java/lang/Integer 4: invokestatic #20 // Method IncLambda.lambda$main$0: (Ljava/lang/Integer;)Ljava/lang/Integer; 7: areturn } コンパイル時に 生成したメソッド

More Decks by Yuichi.Sakuraba

Other Decks in Technology