Slide 1

Slide 1 text

*OWPLF%ZOBNJD ׬શʹཧղͨ͠ *LVP4VZBNB

Slide 2

Slide 2 text

8IBU`TJOWPLFEZOBNJD ”Ϋϥεɾϩʔμʔ͕invokedynamic໋ྩΛؚΉΫϥεΛϩʔυ͢Δͱ͖ɺϝιουݺग़͠ͷλʔήοτ͸·ͩΘ͔ͬ ͍ͯ·ͤΜɻ͜ͷઃܭ͸ɺJVMόΠτίʔυͷଞͷͲͷछྨͷίʔϧɾαΠτʢݺग़͠৔ॴʣͱ΋ҟͳΓ·͢ɻ ” ”invokedynamicͰ͸ɺ໋ྩίʔυ͕σΟεύον͞Εͨͱ͖ʹ࣮ࡍʹݺͼग़͞ΕΔϝιουΛ͸Δ͔ʹॊೈʹܾΊΔ ͜ͱ͕Ͱ͖·͢ɻinvokedynamic໋ྩίʔυ͸ɺ͜ͷॊೈੑΛ࣮ݱ͢ΔͨΊʹɺಈతݺग़͠ΛؚΉΫϥεͷఆ਺ϓʔϧ ಺ʹ͋ΔಛผͳଐੑΛࢀর͍ͯ͠·͢ɻͦͷଐੑ͸ɺϒʔτετϥοϓɾϝιουʢBSMʣͱ ݺ͹Εɺಈతݺग़͠ͷ ੑ࣭Λࢧ͑Δ௥Ճ৘ใΛؚΜͰ͍·͢ɻ ” ”invokedynamic໋ྩͷίʔϧɾαΠτ͸ɺΫϥε͕ϩʔυ͞Εͨͱ͖ʹɺ͍Θ͹ʮະ઀ଓʯͷঢ়ଶʹͳΓ·͢ɻ ࣮ࡍ ʹͲͷϝιουΛݺͼग़͢΂͖͔ΛܾΊΔͨΊʹBSM͕ݺͼग़͞ΕΔͱɺͦͷ݁ՌͰ͋ΔCallSiteΦϒδΣΫτ ͕ ίʔϧɾαΠτʹʮ઀ଓʯ͞Ε·͢ɻ ” — JavaͰͷinvokedynamicʹΑΔϝιουݺग़͠Λཧղ͢Δ

Slide 3

Slide 3 text

ͳΔ΄ͲΘ͔ΒΜ🤔 ೔ຊޠͰ͓̺

Slide 4

Slide 4 text

8IBU`TJOWPLFEZOBNJD w +BWB7.ʹ͸ɺJOWPLF)PHFΠϯετϥΫγϣϯ͕̑ͭ͋Δ w JOWPLFEZOBNJDΛཧղ͢ΔͨΊɺ·ͣ͸΄͔ͷ̐ͭΛݟ͍ͯ͘ — Javaʹ͓͚Δϝιουݺग़͠ͷ࢓૊Έ

Slide 5

Slide 5 text

࿦ΑΓίʔυ w ؀ڥɿ ❯ java -version openjdk version "11.0.9" 2020-10-20 OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.9+11) OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.9+11, mixed mode) w *OWPLFTKBWB package invoke.others; public class Invokes implements IInvoke { public static void main(String[] args) { int i = 1; Invokes.staticMethod(i); Invokes invs = new Invokes(); invs.method(i); IInvoke iinvs = invs; iinvs.interfaceMethod(i); } public int method(int i) { return i; } public static int staticMethod(int i) { return i; } @Override public int interfaceMethod(int i) { return i; } } interface IInvoke { int interfaceMethod(int i); }

Slide 6

Slide 6 text

+7.ϚγϯޠΛ೷͍ͯΈΔ *OWPLFTKBWB package invoke.others; public class Invokes implements IInvoke { public static void main(String[] args) { int i = 1; Invokes.staticMethod(i); Invokes invs = new Invokes(); invs.method(i); IInvoke iinvs = invs; iinvs.interfaceMethod(i); } public int method(int i) { return i; } public static int staticMethod(int i) { return i; } @Override public int interfaceMethod(int i) { return i; } } interface IInvoke { int interfaceMethod(int i); } ❯ javac Invokes.java ❯ javap -v -p -s -constants Invokes.class > Invokes.jvm Compiled from "Invokes.java" public class invoke.others.Invokes implements invoke.others.IInvoke { : public static void main(java.lang.String[]); Code: 0: iconst_1 1: istore_1 2: iload_1 3: invokestatic #2 // Method staticMethod:(I)I 6: pop 7: new #3 // class invoke/others/Invokes 10: dup 11: invokespecial #4 // Method "":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I 20: pop 21: aload_2 22: astore_3 23: aload_3 24: iload_1 25: invokeinterface #6, 2 // InterfaceMethod invoke/others/ IInvoke.interfaceMethod:(I)I 30: pop 31: return *OWPLFTKWN NBJOϝιουͷΈൈਮ

Slide 7

Slide 7 text

+7.ϚγϯޠΛ೷͍ͯΈΔ *OWPLFTKBWB package invoke.others; public class Invokes implements IInvoke { public static void main(String[] args) { int i = 1; Invokes.staticMethod(i); Invokes invs = new Invokes(); invs.method(i); IInvoke iinvs = invs; iinvs.interfaceMethod(i); } public int method(int i) { return i; } public static int staticMethod(int i) { return i; } @Override public int interfaceMethod(int i) { return i; } } interface IInvoke { int interfaceMethod(int i); } ❯ javac Invokes.java ❯ javap -v -p -s -constants Invokes.class > Invokes.jvm Compiled from "Invokes.java" public class invoke.others.Invokes implements invoke.others.IInvoke { : public static void main(java.lang.String[]); Code: 0: iconst_1 1: istore_1 2: iload_1 3: invokestatic #2 // Method staticMethod:(I)I 6: pop 7: new #3 // class invoke/others/Invokes 10: dup 11: invokespecial #4 // Method "":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I 20: pop 21: aload_2 22: astore_3 23: aload_3 24: iload_1 25: invokeinterface #6, 2 // InterfaceMethod invoke/others/ IInvoke.interfaceMethod:(I)I 30: pop 31: return *OWPLFTKWN NBJOϝιουͷΈൈਮ

Slide 8

Slide 8 text

JOWPLFWJSUVBMΛৄ͘͠ public class invoke.others.Invokes implements invoke.others.IInvoke minor version: 0 major version: 55 flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #3 // invoke/others/Invokes super_class: #7 // java/lang/Object interfaces: 1, fields: 0, methods: 5, attributes: 1 Constant pool: #3 = Class #23 // invoke/others/Invokes #5 = Methodref #3.#24 // invoke/others/Invokes.method:(I)I : #15 = Utf8 method #16 = Utf8 (I)I : #24 = NameAndType #15:#16 // method:(I)I : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 : 11: invokespecial #4 // Method "":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I : invokevirtual Operation Invoke instance method; dispatch based on class Format 
 invokevirtual
 indexbyte1
 indexbyte2
 Forms invokevirtual = 182 (0xb6) Operand Stack ..., objectref, [arg1, [arg2 ...]] → ... Description The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (§2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. *OWPLFTKWN ൈਮ 3FGJOWPLFWJSUVBM

Slide 9

Slide 9 text

public class invoke.others.Invokes implements invoke.others.IInvoke minor version: 0 major version: 55 flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #3 // invoke/others/Invokes super_class: #7 // java/lang/Object interfaces: 1, fields: 0, methods: 5, attributes: 1 Constant pool: #3 = Class #23 // invoke/others/Invokes #5 = Methodref #3.#24 // invoke/others/Invokes.method:(I)I : #15 = Utf8 method #16 = Utf8 (I)I : #24 = NameAndType #15:#16 // method:(I)I : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 : 11: invokespecial #4 // Method "":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I : JOWPLFWJSUVBMΛৄ͘͠ aload_ Operation Load reference from local variable Forms aload_2 = 44 (0x2c) Operand Stack ... → ..., objectref Description The must be an index into the local variable array of the current frame (§2.6). iload_ Operation Load int from local variable 
 Forms iload_1 = 27 (0x1b) Operand Stack ... → ..., value Description The must be an index into the local variable array of the current frame (§2.6). *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ astore_ Operation Store reference into local variable Forms astore_2 = 77 (0x4d) Operand Stack ..., objectref → ... Description The must be an index into the local variable array of the current frame (§2.6).

Slide 10

Slide 10 text

🤔 .FUIPEʜ🤔$POTUBOU1PPMʜ🤔 $MBTT'JMFͷߏ଄ΛݟͯΈΑ͏

Slide 11

Slide 11 text

+BWB$MBTTϑΝΠϧͷߏ଄ $IBQUFS5IFDMBTT'JMF'PSNBU ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; } *OWPLFTDMBTT ൈਮ

Slide 12

Slide 12 text

+BWB$MBTTϑΝΠϧͷߏ଄ $IBQUFS5IFDMBTT'JMF'PSNBU ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; } *OWPLFTDMBTT ൈਮ +BWBWFS ݸ $POTUBOU1PPM഑ྻ

Slide 13

Slide 13 text

$POTUBOU1PPM cp_info { u1 tag; u1 info[]; } 5IF$POTUBOU1PPM Constant pool: #1 = Methodref #7.#21 // java/lang/Object."":()V #2 = Methodref #3.#22 // invoke/others/Invokes.staticMethod:(I)I #3 = Class #23 // invoke/others/Invokes #4 = Methodref #3.#21 // invoke/others/Invokes."":()V #5 = Methodref #3.#24 // invoke/others/Invokes.method:(I)I #6 = InterfaceMethodref #8.#25 // invoke/others/IInvoke.interfaceMethod:(I)I #7 = Class #26 // java/lang/Object #8 = Class #27 // invoke/others/IInvoke #9 = Utf8 #10 = Utf8 ()V #11 = Utf8 Code #12 = Utf8 LineNumberTable #13 = Utf8 main #14 = Utf8 ([Ljava/lang/String;)V #15 = Utf8 method #16 = Utf8 (I)I #17 = Utf8 staticMethod #18 = Utf8 interfaceMethod #19 = Utf8 SourceFile #20 = Utf8 Invokes.java #21 = NameAndType #9:#10 // "":()V #22 = NameAndType #17:#16 // staticMethod:(I)I #23 = Utf8 invoke/others/Invokes #24 = NameAndType #15:#16 // method:(I)I #25 = NameAndType #18:#16 // interfaceMethod:(I)I #26 = Utf8 java/lang/Object #27 = Utf8 invoke/others/IInvoke *OWPLFTKWN ൈਮ

Slide 14

Slide 14 text

$POTUBOU1PPMάϥϑߏ଄ *OWPLFTKWN ൈਮ JOWPLFWJSUVBMͷҾ਺ͩͬͨ͸ʜ Constant pool: #1 = Methodref #7.#21 // java/lang/Object."":()V #2 = Methodref #3.#22 // invoke/others/Invokes.staticMethod:(I)I #3 = Class #23 // invoke/others/Invokes #4 = Methodref #3.#21 // invoke/others/Invokes."":()V #5 = Methodref #3.#24 // invoke/others/Invokes.method:(I)I #6 = InterfaceMethodref #8.#25 // invoke/others/IInvoke.interfaceMethod:(I)I #7 = Class #26 // java/lang/Object #8 = Class #27 // invoke/others/IInvoke #9 = Utf8 #10 = Utf8 ()V #11 = Utf8 Code #12 = Utf8 LineNumberTable #13 = Utf8 main #14 = Utf8 ([Ljava/lang/String;)V #15 = Utf8 method #16 = Utf8 (I)I #17 = Utf8 staticMethod #18 = Utf8 interfaceMethod #19 = Utf8 SourceFile #20 = Utf8 Invokes.java #21 = NameAndType #9:#10 // "":()V #22 = NameAndType #17:#16 // staticMethod:(I)I #23 = Utf8 invoke/others/Invokes #24 = NameAndType #15:#16 // method:(I)I #25 = NameAndType #18:#16 // interfaceMethod:(I)I #26 = Utf8 java/lang/Object #27 = Utf8 invoke/others/IInvoke

Slide 15

Slide 15 text

$POTUBOU1PPMάϥϑߏ଄ Constant pool: #1 = Methodref #7.#21 // java/lang/Object."":()V #2 = Methodref #3.#22 // invoke/others/Invokes.staticMethod:(I)I #3 = Class #23 // invoke/others/Invokes #4 = Methodref #3.#21 // invoke/others/Invokes."":()V #5 = Methodref #3.#24 // invoke/others/Invokes.method:(I)I #6 = InterfaceMethodref #8.#25 // invoke/others/IInvoke.interfaceMethod:(I)I #7 = Class #26 // java/lang/Object #8 = Class #27 // invoke/others/IInvoke #9 = Utf8 #10 = Utf8 ()V #11 = Utf8 Code #12 = Utf8 LineNumberTable #13 = Utf8 main #14 = Utf8 ([Ljava/lang/String;)V #15 = Utf8 method #16 = Utf8 (I)I #17 = Utf8 staticMethod #18 = Utf8 interfaceMethod #19 = Utf8 SourceFile #20 = Utf8 Invokes.java #21 = NameAndType #9:#10 // "":()V #22 = NameAndType #17:#16 // staticMethod:(I)I #23 = Utf8 invoke/others/Invokes #24 = NameAndType #15:#16 // method:(I)I #25 = NameAndType #18:#16 // interfaceMethod:(I)I #26 = Utf8 java/lang/Object #27 = Utf8 invoke/others/IInvoke *OWPLFTKWN ൈਮ JOWPLFWJSUVBMͷҾ਺ͩͬͨ͸ʜ

Slide 16

Slide 16 text

$POTUBOU1PPMάϥϑߏ଄ Constant pool: #1 = Methodref #7.#21 // java/lang/Object."":()V #2 = Methodref #3.#22 // invoke/others/Invokes.staticMethod:(I)I #3 = Class #23 // invoke/others/Invokes #4 = Methodref #3.#21 // invoke/others/Invokes."":()V #5 = Methodref #3.#24 // invoke/others/Invokes.method:(I)I #6 = InterfaceMethodref #8.#25 // invoke/others/IInvoke.interfaceMethod:(I)I #7 = Class #26 // java/lang/Object #8 = Class #27 // invoke/others/IInvoke #9 = Utf8 #10 = Utf8 ()V #11 = Utf8 Code #12 = Utf8 LineNumberTable #13 = Utf8 main #14 = Utf8 ([Ljava/lang/String;)V #15 = Utf8 method #16 = Utf8 (I)I #17 = Utf8 staticMethod #18 = Utf8 interfaceMethod #19 = Utf8 SourceFile #20 = Utf8 Invokes.java #21 = NameAndType #9:#10 // "":()V #22 = NameAndType #17:#16 // staticMethod:(I)I #23 = Utf8 invoke/others/Invokes #24 = NameAndType #15:#16 // method:(I)I #25 = NameAndType #18:#16 // interfaceMethod:(I)I #26 = Utf8 java/lang/Object #27 = Utf8 invoke/others/IInvoke *OWPLFTKWN ൈਮ JOWPLFWJSUVBMͷҾ਺ͩͬͨ͸ʜ

Slide 17

Slide 17 text

$POTUBOU1PPM.FUIPESFG cp_info { u1 tag; u1 info[]; } // CONSTANT_Methodref_info (Extends cp_info) CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } 5IF$0/45"/5@.FUIPESFG@JOGP TUSVDUVSFT tag The tag item of a CONSTANT_Methodref_info structure has the value CONSTANT_Methodref (10). class_index The value of the class_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Class_info structure (§4.4.1) In a CONSTANT_Methodref_info structure, the class_index item must be a class type, not an interface type. name_and_type_index The value of the name_and_type_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_NameAndType_info structure (§4.4.6). *OWPLFTDMBTT ൈਮ Constant pool: : #5 = Methodref #3.#24 // invoke/others/Invokes.method:(I)I :

Slide 18

Slide 18 text

.FUIPET method_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; } .FUIPET access_flags The value of the access_flags item is a mask of flags used to denote access permission to and properties of this method. The interpretation of each flag, when set, is specified in Table 4.6-A. name_index The value of the name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7). descriptor_index The value of the descriptor_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing a valid method descriptor (§4.3.3). attributes_count The value of the attributes_count item indicates the number of additional attributes of this method. attributes[] Each value of the attributes table must be an attribute_info structure (§4.7). Constant Pool: #15 = Utf8 method #16 = Utf8 (I)I public int method(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: iload_1 1: ireturn LineNumberTable: line 13: 0 public int method(int i) { return i; }

Slide 19

Slide 19 text

.FUIPET method_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; } .FUIPET access_flags The value of the access_flags item is a mask of flags used to denote access permission to and properties of this method. The interpretation of each flag, when set, is specified in Table 4.6-A. name_index The value of the name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7). descriptor_index The value of the descriptor_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing a valid method descriptor (§4.3.3). attributes_count The value of the attributes_count item indicates the number of additional attributes of this method. attributes[] Each value of the attributes table must be an attribute_info structure (§4.7). Constant Pool: #15 = Utf8 method #16 = Utf8 (I)I public int method(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: iload_1 1: ireturn LineNumberTable: line 13: 0 public int method(int i) { return i; } BDDFTT@ fl BHTYQVCMJD OBNF@JOEFY $1NFUIPE EFTDSJQUPS@JOEFY $1 * * BUUSJCVUF<>$PEF BUUSJCVUFT@DPVOU

Slide 20

Slide 20 text

$PEF"UUSJCVUF Code_attribute { u2 attribute_name_index; u4 attribute_length; u2 max_stack; u2 max_locals; u4 code_length; u1 code[code_length]; u2 exception_table_length; { u2 start_pc; u2 end_pc; u2 handler_pc; u2 catch_type; } exception_table[exception_table_length]; u2 attributes_count; attribute_info attributes[attributes_count]; } 5IF$PEF"UUSJCVUF Constant Pool: #11 = Utf8 Code public int method(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: iload_1 1: ireturn LineNumberTable: line 13: 0 public int method(int i) { return i; } attribute_name_index The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7) representing the string "Code". attribute_length The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. max_stack The value of the max_stack item gives the maximum depth of the operand stack of this method (§2.6.2) at any point during execution of the method. max_locals The value of the max_locals item gives the number of local variables in the local variable array allocated upon invocation of this method (§2.6.1), including the local variables used to pass parameters to the method on its invocation. code_length The value of the code_length item gives the number of bytes in the code array for this method. code[] The code array gives the actual bytes of Java Virtual Machine code that implement the method.

Slide 21

Slide 21 text

$PEF"UUSJCVUF Code_attribute { u2 attribute_name_index; u4 attribute_length; u2 max_stack; u2 max_locals; u4 code_length; u1 code[code_length]; u2 exception_table_length; { u2 start_pc; u2 end_pc; u2 handler_pc; u2 catch_type; } exception_table[exception_table_length]; u2 attributes_count; attribute_info attributes[attributes_count]; } 5IF$PEF"UUSJCVUF Constant Pool: #11 = Utf8 Code public int method(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: iload_1 1: ireturn LineNumberTable: line 13: 0 public int method(int i) { return i; } attribute_name_index The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7) representing the string "Code". attribute_length The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. max_stack The value of the max_stack item gives the maximum depth of the operand stack of this method (§2.6.2) at any point during execution of the method. max_locals The value of the max_locals item gives the number of local variables in the local variable array allocated upon invocation of this method (§2.6.1), including the local variables used to pass parameters to the method on its invocation. code_length The value of the code_length item gives the number of bytes in the code array for this method. code[] The code array gives the actual bytes of Java Virtual Machine code that implement the method. BUUSJCVUF@OBNF@JOEFY $1$PEF BUUSJCVUF@MFOHUI NBY@MPDBMT NBY@TUBDL DPEF@MFOHUI DPEF<> JMPBE@Y# JSFUVSOY"$ FYDFQUJPO@UBCMF@MFOHUI BUUSJCVUFT@DPVOU BUUSJCVUFT<> -JOF/VNCFS5BCMF

Slide 22

Slide 22 text

public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: iconst_1 1: istore_1 : 11: invokespecial #4 // Method "":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I : 3FJOWPLFWJSUVBMΛৄ͘͠ *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ public static void main(String[] args) { int i = 1; : Invokes invs = new Invokes(); invs.method(i); *OWPLFTKBWB -PDBM7BSJBCMFT<> 0QFSBOE4UBDL 4USJOH<> BSHT *OU *OWPLFT JOWT 1$JOWPLFTQFDJBM YC ͷ࣮ߦ௚ޙ $VSSFOU'SBNF 1$

Slide 23

Slide 23 text

public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: iconst_1 1: istore_1 : 11: invokespecial #4 // Method "":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I : 3FJOWPLFWJSUVBMΛৄ͘͠ *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ public static void main(String[] args) { int i = 1; : Invokes invs = new Invokes(); invs.method(i); *OWPLFTKBWB -PDBM7BSJBCMFT<> 0QFSBOE4UBDL 4USJOH<> BSHT *OU *OWPLFT JOWT *OWPLFT JOWT 1$BTUPSF@ YE $VSSFOU'SBNF 1$ Operation Store reference into local variable

Slide 24

Slide 24 text

public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: iconst_1 1: istore_1 : 11: invokespecial #4 // Method "":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I : 3FJOWPLFWJSUVBMΛৄ͘͠ *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ public static void main(String[] args) { int i = 1; : Invokes invs = new Invokes(); invs.method(i); *OWPLFTKBWB -PDBM7BSJBCMFT<> 0QFSBOE4UBDL 4USJOH<> BSHT *OU *OWPLFT JOWT 1$BMPBE@ YD *OWPLFT JOWT $VSSFOU'SBNF 1$ Operation Load reference from local variable

Slide 25

Slide 25 text

public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: iconst_1 1: istore_1 : 11: invokespecial #4 // Method "":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I : 3FJOWPLFWJSUVBMΛৄ͘͠ *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ public static void main(String[] args) { int i = 1; : Invokes invs = new Invokes(); invs.method(i); *OWPLFTKBWB -PDBM7BSJBCMFT<> 0QFSBOE4UBDL 4USJOH<> BSHT *OU *OWPLFT JOWT 1$JMPBE@ YC *OWPLFT JOWT *OU $VSSFOU'SBNF 1$ Operation Load int from local variable

Slide 26

Slide 26 text

public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: iconst_1 1: istore_1 : 11: invokespecial #4 // Method "":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I : 3FJOWPLFWJSUVBMΛৄ͘͠ *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ public static void main(String[] args) { int i = 1; : Invokes invs = new Invokes(); invs.method(i); *OWPLFTKBWB -PDBM7BSJBCMFT<> 0QFSBOE4UBDL 4USJOH<> BSHT *OU *OWPLFT JOWT 1$JOWPLFWJSUVBM YC -PPLVQUIFNFUIPE DSFBUFOFX'SBNF *OWPLFT JOWT *OU $VSSFOU'SBNF 1$ /FX 'SBNF Operation Invoke instance method; dispatch based on class

Slide 27

Slide 27 text

3FJOWPLFWJSUVBMΛৄ͘͠ *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ *OWPLFTKBWB -PDBM7BSJBCMFT<> 0QFSBOE4UBDL *OWPLFT JOWT *OU 1$JOWPLFWJSUVBM YC KVNQUPUIFNFUIPET JOWPLF public int method(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: iload_1 1: ireturn LineNumberTable: line 13: 0 public int method(int i) { return i; } $VSSFOU'SBNF 1$ 1SFW 'SBNF NBJO

Slide 28

Slide 28 text

3FJOWPLFWJSUVBMΛৄ͘͠ *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ *OWPLFTKBWB -PDBM7BSJBCMFT<> 0QFSBOE4UBDL *OWPLFT JOWT *OU 1$JMPBE@ YC public int method(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: iload_1 1: ireturn LineNumberTable: line 13: 0 public int method(int i) { return i; } $VSSFOU'SBNF 1$ 1SFW 'SBNF NBJO *OU

Slide 29

Slide 29 text

3FJOWPLFWJSUVBMΛৄ͘͠ *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ *OWPLFTKBWB -PDBM7BSJBCMFT<> 0QFSBOE4UBDL *OWPLFT JOWT *OU 1$JSFUVSO YBD public int method(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: iload_1 1: ireturn LineNumberTable: line 13: 0 public int method(int i) { return i; } $VSSFOU'SBNF 1$ 1SFW 'SBNF NBJO *OU Operation Return int from method

Slide 30

Slide 30 text

public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: iconst_1 1: istore_1 : 11: invokespecial #4 // Method "":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I : 3FJOWPLFWJSUVBMΛৄ͘͠ *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ public static void main(String[] args) { int i = 1; : Invokes invs = new Invokes(); invs.method(i); *OWPLFTKBWB -PDBM7BSJBCMFT<> 0QFSBOE4UBDL 4USJOH<> BSHT *OU *OWPLFT JOWT 1$JOWPLFWJSUVBM YC QVTISFUVSFOEWBMVFUPPQFSBOETUBDL $VSSFOU'SBNF 1$ *OU 1SFW 'SBNF

Slide 31

Slide 31 text

*OWPLFEZOBNJDҎ֎ͷJOWPLF·ͱΊ w جຊతʹ΍Δ͜ͱ͸ಉ͡ w .FUIPEMPPLVQDSFBUFGSBNFPQFSBOEUPMPDBMWBMSFUVSO w .FUIPE-PPLVQͷํ๏΍࣮ߦ࣌ͷPQFSBOETUBDL͕গ͠ҟͳΔ w ίϯύΠϧ࣌ʹ࣮ߦର৅͕Ұҙʹܾ·Δ࣮ߦର৅0CKFDUΛPQFSBOEʹੵ·ͳ͍ 㾎JOWPLFTQFDJBMʜDPOTUSVDUPS QSJWBUFNFUIPE 㾎JOWPLFTUBUJDʜTUBUJDNFUIPE w ϙϦϞʔϑΟζϜͷͨΊɺίϯύΠϧ࣌ʹϧοΫΞοϓΛߦ͏ 㾎JOWPLFWJSUVBMʜJOTUBODFNFUIPE 㾎JOWPLFJOUFSGBDFʜNFUIPEWJBJOUFSGBDF

Slide 32

Slide 32 text

*OWPLFEZOBNJDҎ֎ͷJOWPLFͷ੍໿ w ϝιουϧοΫΞοϓͷ࢓༷͕+BWBݴޠ࢓༷Ͱ੍ݶ͞ΕΔ w +BWBͷఆΊΔΫϥε࢓༷ɾϙϦϞʔϑΟζϜͷ࿮૊ΈͰ͔͠ݕࡧͰ͖ͳ͍ w ΠϯετϥΫγϣϯΛσΟεύον͢Δࡍɺ࣮ߦର৅ͷϝιου͕͢Ͱʹ +7.ʹଘࡏ͍ͯ͠Δඞཁ͕͋Δ w ਖ਼֬ʹ͸ॴଐ͢ΔΫϥεϩʔμ͔ΒݕࡧͰ͖Δঢ়ଶͰ͋Δඞཁ͕͋Δ

Slide 33

Slide 33 text

׬શཧղ🙌

Slide 34

Slide 34 text

8IBU`TJOWPLFEZOBNJD ”Ϋϥεɾϩʔμʔ͕invokedynamic໋ྩΛؚΉΫϥεΛϩʔυ͢Δͱ͖ɺϝιουݺग़͠ͷλʔήοτ͸·ͩΘ͔ͬ ͍ͯ·ͤΜɻ͜ͷઃܭ͸ɺJVMόΠτίʔυͷଞͷͲͷछྨͷίʔϧɾαΠτʢݺग़͠৔ॴʣͱ΋ҟͳΓ·͢ɻ ” ”invokedynamicͰ͸ɺ໋ྩίʔυ͕σΟεύον͞Εͨͱ͖ʹ࣮ࡍʹݺͼग़͞ΕΔϝιουΛ͸Δ͔ʹॊೈʹܾΊΔ ͜ͱ͕Ͱ͖·͢ɻinvokedynamic໋ྩίʔυ͸ɺ͜ͷॊೈੑΛ࣮ݱ͢ΔͨΊʹɺಈతݺग़͠ΛؚΉΫϥεͷఆ਺ϓʔϧ ಺ʹ͋ΔಛผͳଐੑΛࢀর͍ͯ͠·͢ɻͦͷଐੑ͸ɺϒʔτετϥοϓɾϝιουʢBSMʣͱ ݺ͹Εɺಈతݺग़͠ͷ ੑ࣭Λࢧ͑Δ௥Ճ৘ใΛؚΜͰ͍·͢ɻ ” ”invokedynamic໋ྩͷίʔϧɾαΠτ͸ɺΫϥε͕ϩʔυ͞Εͨͱ͖ʹɺ͍Θ͹ʮະ઀ଓʯͷঢ়ଶʹͳΓ·͢ɻ ࣮ࡍ ʹͲͷϝιουΛݺͼग़͢΂͖͔ΛܾΊΔͨΊʹBSM͕ݺͼग़͞ΕΔͱɺͦͷ݁ՌͰ͋ΔCallSiteΦϒδΣΫτ ͕ ίʔϧɾαΠτʹʮ઀ଓʯ͞Ε·͢ɻ ” — JavaͰͷinvokedynamicʹΑΔϝιουݺग़͠Λཧղ͢Δ ೔ຊޠͰ͓̺ Θ͔Δ

Slide 35

Slide 35 text

࿦ΑΓίʔυɿϚγϯޠΛ೷͍ͯΈΔ package invoke.dynamic; public class InvokeDynamicSimple { public static void main(String[] args) { Runnable r = () -> System.out.println("Hello"); r.run(); } } ❯ javac InvokeDynamicSimple.java ❯ javap -v -s -constants InvokeDynamicSimple.class > InvokeDynamicSimple.jvm public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) 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: aload_1 7: invokeinterface #3, 1 // InterfaceMethod java/lang/Runnable.run:()V 12: return } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/ MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V *OWPLF%ZOBNJD4JNQMFKBWB *OWPLF%ZOBNJD4JNQMFKWN w -BNCEB͕*OWPLF%ZOBNJDͰ࣮ݱ͞Εͯ ͍Δ͜ͱ͸Α͘஌ΒΕ͍ͯΔͷͰɺͱΓ͋ ͑ͣίϯύΠϧσίϯύΠϧ

Slide 36

Slide 36 text

࿦ΑΓίʔυɿϚγϯޠΛ೷͍ͯΈΔ package invoke.dynamic; public class InvokeDynamicSimple { public static void main(String[] args) { Runnable r = () -> System.out.println("Hello"); r.run(); } } ❯ javac InvokeDynamicSimple.java ❯ javap -v -s -constants InvokeDynamicSimple.class > InvokeDynamicSimple.jvm public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) 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: aload_1 7: invokeinterface #3, 1 // InterfaceMethod java/lang/Runnable.run:()V 12: return } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/ MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V *OWPLF%ZOBNJD4JNQMFKBWB *OWPLF%ZOBNJD4JNQMFKWN w 'PVOEJOWPLFEZOBNJD w $1Λࢀর͍ͯ͠Δ͜ͱ͸૝૾͕ͭ͘ w SVO -KBWBMBOH3VOOBCMF w *OWPLF%ZOBNJD$1 w #PPUTUSBQ.FUIPET w 4ZTUFNPVUQSJOUMO Ͳ͍ͬͨ͜ ͜Μͳγάωνϟͷϝιουͳ͍Ͱ͢ ୭Ͱ͔͢ʁʁʁ ୭Ͱ͔͢ʁʁʁ

Slide 37

Slide 37 text

࿦ΑΓίʔυɿϚγϯޠΛ೷͍ͯΈΔ ❯ javac InvokeDynamicSimple.java ❯ javap -v -s -constants InvokeDynamicSimple.class > InvokeDynamicSimple.jvm public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) 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: aload_1 7: invokeinterface #3, 1 // InterfaceMethod java/lang/Runnable.run:()V 12: return } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/ MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V *OWPLF%ZOBNJD4JNQMFKWN invokedynamic Operation Invoke a dynamically-computed call site Format invokedynamic
 indexbyte1
 indexbyte2
 0
 0
 Description First, the unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (§2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a dynamically-computed call site (§5.1). The values of the third and fourth operand bytes must always be zero. : The symbolic reference is resolved (§5.4.3.6) for this specific invokedynamic instruction to obtain a reference to an instance of java.lang.invoke.CallSite. The instance of java.lang.invoke. The instance of java.lang.invoke.CallSite indicates a target method handle. The invocation occurs as if by execution of an invokevirtual instruction that indicates a run-time constant pool index to a symbolic reference R JOWPLFEZOBNJD w $BMM4JUFͱ΍ΒΛJOWPLFWJSUVBMͰ࣮ߦ͢Δ Β͍͠ʜ ͜Μͳγάωνϟͷϝιουͳ͍Ͱ͢ ୭Ͱ͔͢ʁʁʁ ୭Ͱ͔͢ʁʁʁ

Slide 38

Slide 38 text

8IBU`TJOWPLFEZOBNJD ”Ϋϥεɾϩʔμʔ͕invokedynamic໋ྩΛؚΉΫϥεΛϩʔυ͢Δͱ͖ɺϝιουݺग़͠ͷλʔήοτ͸·ͩΘ͔ͬ ͍ͯ·ͤΜɻ͜ͷઃܭ͸ɺJVMόΠτίʔυͷଞͷͲͷछྨͷίʔϧɾαΠτʢݺग़͠৔ॴʣͱ΋ҟͳΓ·͢ɻ ” ”invokedynamicͰ͸ɺ໋ྩίʔυ͕σΟεύον͞Εͨͱ͖ʹ࣮ࡍʹݺͼग़͞ΕΔϝιουΛ͸Δ͔ʹॊೈʹܾΊΔ ͜ͱ͕Ͱ͖·͢ɻinvokedynamic໋ྩίʔυ͸ɺ͜ͷॊೈੑΛ࣮ݱ͢ΔͨΊʹɺಈతݺग़͠ΛؚΉΫϥεͷఆ਺ϓʔϧ ಺ʹ͋ΔಛผͳଐੑΛࢀর͍ͯ͠·͢ɻͦͷଐੑ͸ɺϒʔτετϥοϓɾϝιουʢBSMʣͱ ݺ͹Εɺಈతݺग़͠ͷ ੑ࣭Λࢧ͑Δ௥Ճ৘ใΛؚΜͰ͍·͢ɻ ” ”invokedynamic໋ྩͷίʔϧɾαΠτ͸ɺΫϥε͕ϩʔυ͞Εͨͱ͖ʹɺ͍Θ͹ʮະ઀ଓʯͷঢ়ଶʹͳΓ·͢ɻ ࣮ࡍ ʹͲͷϝιουΛݺͼग़͢΂͖͔ΛܾΊΔͨΊʹBSM͕ݺͼग़͞ΕΔͱɺͦͷ݁ՌͰ͋ΔCallSiteΦϒδΣΫτ ͕ ίʔϧɾαΠτʹʮ઀ଓʯ͞Ε·͢ɻ ” — JavaͰͷinvokedynamicʹΑΔϝιουݺग़͠Λཧղ͢Δ Θ͔Δ ͖͕͢Δ ͖ͬ͞ݟͨ ೔ຊޠͰ͓̺

Slide 39

Slide 39 text

#PPU4USBQ.FUIPE#4. +BWBԾ૝ϚγϯɾΨΠυඇ+BWBݴޠͷαϙʔτ ϒʔτετϥοϓɾϝιουͷ໭Γܕ͸java.lang.invoke.CallSiteͰ͋Δඞཁ͕͋Γ·͢ɻCallSiteΦϒδΣΫτ͸ɺinvokedynamic໋ྩͱͦΕ͕ϦϯΫ ͞ΕΔϝιουɾϋϯυϧͷϦϯΫঢ়ଶΛද͠·͢ɻ ϒʔτετϥοϓɾϝιου͸ɺ࣍ͷύϥϝʔλΛ3ͭҎ্औΓ·͢ɻ • MethodHandles.LookupΦϒδΣΫτ: invokedynamic໋ྩͷίϯςΩετ಺ͰϝιουɾϋϯυϧΛ࡞੒͢ΔϑΝΫτϦɻ • StringΦϒδΣΫτ: ಈతίʔϧɾαΠτ಺Ͱݴٴ͞ΕΔϝιου໊ɻ • MethodTypeΦϒδΣΫτ: ಈతίʔϧɾαΠτͷղܾࡁܕγάχνϟɻ • invokedynamic໋ྩʹର͢Δ1ͭҎ্ͷ௥Ճͷ੩తҾ਺: ఆ਺ϓʔϧ͔ΒऔΓग़͞ΕΔΦϓγϣϯͷҾ਺ͷ໨త͸ɺݴޠ࣮૷ऀ͕ϒʔτετϥο ϓɾϝιουʹศརͳ௥ՃϝλσʔλΛ҆શ͔ͭίϯύΫτʹΤϯίʔυ͢ΔͷΛࢧԉ͢Δ͜ͱͰ͢ɻ֤ίʔϧɾαΠτʹ͸ಠࣗͷϒʔτετϥο ϓɾϝιου͕ࢦఆ͞ΕΔՄೳੑ͕͋ΔͨΊɺݪଇͱ໊ͯ͠લͱ௥ՃҾ਺͸৑௕ʹͳΓ·͢ɻͨͩ͠ɺͦͷΑ͏ͳӡ༻Ͱ͸͓ͦΒ͘ɺେ͖ͳΫϥ εɾϑΝΠϧ΍ఆ਺ϓʔϧ͕ੜ੒͞Ε·͢ɻ BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V

Slide 40

Slide 40 text

#PPU4USBQ.FUIPE#4. +BWBԾ૝ϚγϯɾΨΠυඇ+BWBݴޠͷαϙʔτ ϒʔτετϥοϓɾϝιουͷ໭Γܕ͸java.lang.invoke.CallSiteͰ͋Δඞཁ͕͋Γ·͢ɻCallSiteΦϒδΣΫτ͸ɺinvokedynamic໋ྩͱͦΕ͕ϦϯΫ ͞ΕΔϝιουɾϋϯυϧͷϦϯΫঢ়ଶΛද͠·͢ɻ ϒʔτετϥοϓɾϝιου͸ɺ࣍ͷύϥϝʔλΛ3ͭҎ্औΓ·͢ɻ • MethodHandles.LookupΦϒδΣΫτ: invokedynamic໋ྩͷίϯςΩετ಺ͰϝιουɾϋϯυϧΛ࡞੒͢ΔϑΝΫτϦɻ • StringΦϒδΣΫτ: ಈతίʔϧɾαΠτ಺Ͱݴٴ͞ΕΔϝιου໊ɻ • MethodTypeΦϒδΣΫτ: ಈతίʔϧɾαΠτͷղܾࡁܕγάχνϟɻ • invokedynamic໋ྩʹର͢Δ1ͭҎ্ͷ௥Ճͷ੩తҾ਺: ఆ਺ϓʔϧ͔ΒऔΓग़͞ΕΔΦϓγϣϯͷҾ਺ͷ໨త͸ɺݴޠ࣮૷ऀ͕ϒʔτετϥο ϓɾϝιουʹศརͳ௥ՃϝλσʔλΛ҆શ͔ͭίϯύΫτʹΤϯίʔυ͢ΔͷΛࢧԉ͢Δ͜ͱͰ͢ɻ֤ίʔϧɾαΠτʹ͸ಠࣗͷϒʔτετϥο ϓɾϝιου͕ࢦఆ͞ΕΔՄೳੑ͕͋ΔͨΊɺݪଇͱ໊ͯ͠લͱ௥ՃҾ਺͸৑௕ʹͳΓ·͢ɻͨͩ͠ɺͦͷΑ͏ͳӡ༻Ͱ͸͓ͦΒ͘ɺେ͖ͳΫϥ εɾϑΝΠϧ΍ఆ਺ϓʔϧ͕ੜ੒͞Ε·͢ɻ BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ௥Ճͷ੩తҾ਺ σϑΥϧτҾ਺ +7.͕ܭࢉऔಘ ฦΓ஋

Slide 41

Slide 41 text

🤔 $BMM4JUFʜ.FUIPE)BOEMFʜ .FUIPE5ZQFʜ

Slide 42

Slide 42 text

KBWBMBOHJOWPLFQBDLBHF $BMM4JUF .FUIPE)BOEMF .FUIPE5ZQF package invoke.dynamic; import java.lang.invoke.CallSite; import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; public class InvokeViaCallSite { public static void main(String[] args) throws Throwable { InvokeViaCallSite ivcs = new InvokeViaCallSite(); CallSite cs = ivcs.getPrintHelloCallSite(); // invoke the method using bundled method handle cs.getTarget().invoke(ivcs, "Ikuo"); } private CallSite getPrintHelloCallSite() throws Exception { MethodHandles.Lookup lk = MethodHandles.lookup(); // return type, arguments MethodType mt = MethodType.methodType(void.class, String.class); // ׬શम০ࢠʹඞཁͳΫϥε৘ใɺϝιου໊ɺϝιουγάωνϟΛ౉͠ɺϝιουΛLookup͢Δ MethodHandle mh = lk.findVirtual(getClass(), "printHello", mt); return new ConstantCallSite(mh); } private void printHello(String name) { System.out.println("Hello " + name + "!"); } } *OWPLF7JB$BMM4JUFKBWB

Slide 43

Slide 43 text

KBWBMBOHJOWPLFQBDLBHF $BMM4JUF .FUIPE)BOEMF .FUIPE5ZQF package invoke.dynamic; import java.lang.invoke.CallSite; import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; public class InvokeViaCallSite { public static void main(String[] args) throws Throwable { InvokeViaCallSite ivcs = new InvokeViaCallSite(); CallSite cs = ivcs.getPrintHelloCallSite(); // invoke the method using bundled method handle cs.getTarget().invoke(ivcs, "Ikuo"); } private CallSite getPrintHelloCallSite() throws Exception { MethodHandles.Lookup lk = MethodHandles.lookup(); // return type, arguments MethodType mt = MethodType.methodType(void.class, String.class); // ׬શम০ࢠʹඞཁͳΫϥε৘ใɺϝιου໊ɺϝιουγάωνϟΛ౉͠ɺϝιουΛLookup͢Δ MethodHandle mh = lk.findVirtual(getClass(), "printHello", mt); return new ConstantCallSite(mh); } private void printHello(String name) { System.out.println("Hello " + name + "!"); } } *OWPLF7JB$BMM4JUFKBWB NFUIPEΛݕࡧ͢ΔͨΊͷ0CKFDU NFUIPEͷܕʢEFTDSJQUPS NFUIPE΁ͷࢀর .FUIPE)BOEMFͷίϯςφ UBSHFU.FUIPE)BOEMF ϝιουΛ࣮ߦ

Slide 44

Slide 44 text

w $BMM4JUF w .FUIPE)BOEMFͷίϯςφΫϥεʢ$BMM4JUFIBTB.FUIPE)BOEMFʣ w .FUIPE)BOEMF w .FUIPE΁ͷࢀর w .FUIPE5ZQF w ϝιουσΟεΫϦϓλʢฦΓ஋ͱҾ਺ͷܕʣ KBWBMBOHJOWPLFQBDLBHF $BMM4JUF .FUIPE)BOEMF .FUIPE5ZQF

Slide 45

Slide 45 text

JOWPLFEZOBNJDཁ͢Δʹʜ w *OWPLFEZOBNJD໋ྩΛॳճʹ࣮ߦ͢Δͱ͖ɺ#PPUTUSBQ.FUIPEʹఆٛ͞Ε ͍ͯΔϝιουΛ࣮ߦ͢Δ w $BMM4JUFΦϒδΣΫτ͕ฦͬͯ͘ΔͷͰɺ͜ΕΛl઀ଓzʢ࣍ճҎ߱͸͜ͷ $BMM4JUFͰϝιουΛ࣮ߦ͢Δʣ͠ɺόϯυϧ͞Εͨ.FUIPE)BOEMFΛ࣮ߦ ͢Δ w ࣮ߦ͢Δର৅ΛܾΊΔํ๏Λzಈతʹzࢦఆ͢Δ͘͠Έ͕ɺϚγϯޠϨϕϧͰ ఏڙ͞Εͨ🙌

Slide 46

Slide 46 text

׬શཧղ🙌

Slide 47

Slide 47 text

ೳॻ͖͸͍͍ɺ όΠφϦΛݟͤΖ

Slide 48

Slide 48 text

package invoke.dynamic; public class InvokeDynamicSimple { public static void main(String[] args) { Runnable r = () -> System.out.println("Hello"); r.run(); } } ❯ javac InvokeDynamicSimple.java ❯ javap -v -s -constants InvokeDynamicSimple.class > InvokeDynamicSimple.jvm public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) 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: aload_1 7: invokeinterface #3, 1 // InterfaceMethod java/lang/Runnable.run:()V 12: return } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/ invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V *OWPLF%ZOBNJD4JNQMFKBWB *OWPLF%ZOBNJD4JNQMFKWN w ݟ׳Εͳ͍ਓͨͪ w *OWPLF%ZOBNJD$1 w .FUIPE)BOEMF$1 w *OWPLFEZOBNJDJOTUSVDUJPO w *OOFS$MBTT-PPLVQ w #PPUTUSBQ.FUIPE ࿦ΑΓόΠφϦJOWPLFEZOBNJD

Slide 49

Slide 49 text

package invoke.dynamic; public class InvokeDynamicSimple { public static void main(String[] args) { Runnable r = () -> System.out.println("Hello"); r.run(); } } ❯ javac InvokeDynamicSimple.java ❯ javap -v -s -constants InvokeDynamicSimple.class > InvokeDynamicSimple.jvm public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) 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: aload_1 7: invokeinterface #3, 1 // InterfaceMethod java/lang/Runnable.run:()V 12: return } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/ invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V *OWPLF%ZOBNJD4JNQMFKBWB w ݟ׳Εͳ͍ਓͨͪ w *OWPLF%ZOBNJD$1 w .FUIPE)BOEMF$1 w *OWPLFEZOBNJDJOTUSVDUJPO w *OOFS$MBTT-PPLVQ w #PPUTUSBQ.FUIPE ࿦ΑΓόΠφϦJOWPLFEZOBNJD *OWPLF%ZOBNJD4JNQMFKWN

Slide 50

Slide 50 text

࿦ΑΓόΠφϦ package invoke.dynamic; public class InvokeDynamicSimple { public static void main(String[] args) { Runnable r = () -> System.out.println("Hello"); r.run(); } } *OWPLF%ZOBNJD4JNQMFKBWB invokedynamic Operation Invoke a dynamically-computed call site Format invokedynamic
 indexbyte1
 indexbyte2
 0
 0
 Forms invokedynamic = 186 (0xba) Description First, the unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (§2.6), The values of the third and fourth operand bytes must always be zero. JOWPLFEZOBNJD YCB public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 51

Slide 51 text

࿦ΑΓόΠφϦ package invoke.dynamic; public class InvokeDynamicSimple { public static void main(String[] args) { Runnable r = () -> System.out.println("Hello"); r.run(); } } public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; *OWPLF%ZOBNJD4JNQMFKBWB invokedynamic Operation Invoke a dynamically-computed call site Format invokedynamic
 indexbyte1
 indexbyte2
 0
 0
 Forms invokedynamic = 186 (0xba) Description First, the unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (§2.6), The values of the third and fourth operand bytes must always be zero. JOWPLFEZOBNJD YCB *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 52

Slide 52 text

࿦ΑΓόΠφϦ CONSTANT_InvokeDynamic_info { u1 tag; u2 bootstrap_method_attr_index; u2 name_and_type_index; } public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; : BootstrapMethods: 0: #20 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:( : )Ljava/lang/invoke/CallSite; 5IF$0/45"/5@*OWPLF%ZOBNJD@JOGP 4USVDUVSFT tag The tag item of a CONSTANT_InvokeDynamic_info structure has the value CONSTANT_InvokeDynamic (18). bootstrap_method_attr_index The value of the bootstrap_method_attr_index item must be a valid index into the bootstrap_methods array of the bootstrap method table of this class file (§4.7.23). name_and_type_index The value of the name_and_type_index item must be a valid index into the constant_pool table. In a CONSTANT_InvokeDynamic_info structure, the indicated descriptor must be a method descriptor (§4.3.3). *OWPLF%ZOBNJD$POTUBOU1PPM *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 53

Slide 53 text

࿦ΑΓόΠφϦ CONSTANT_InvokeDynamic_info { u1 tag; u2 bootstrap_method_attr_index; u2 name_and_type_index; } public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; : BootstrapMethods: 0: #20 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:( : )Ljava/lang/invoke/CallSite; 5IF$0/45"/5@*OWPLF%ZOBNJD@JOGP 4USVDUVSFT tag The tag item of a CONSTANT_InvokeDynamic_info structure has the value CONSTANT_InvokeDynamic (18). bootstrap_method_attr_index The value of the bootstrap_method_attr_index item must be a valid index into the bootstrap_methods array of the bootstrap method table of this class file (§4.7.23). name_and_type_index The value of the name_and_type_index item must be a valid index into the constant_pool table. In a CONSTANT_InvokeDynamic_info structure, the indicated descriptor must be a method descriptor (§4.3.3). *OWPLF%ZOBNJD$POTUBOU1PPM *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 54

Slide 54 text

࿦ΑΓόΠφϦ BootstrapMethods_attribute { u2 attribute_name_index; u4 attribute_length; u2 num_bootstrap_methods; { u2 bootstrap_method_ref; u2 num_bootstrap_arguments; u2 bootstrap_arguments[num_bootstrap_arguments]; } bootstrap_methods[num_bootstrap_methods]; } Constant pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #19 = Utf8 BootstrapMethods #20 = MethodHandle 6:#33 // 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; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V 5IF#PPUTUSBQ.FUIPET"UUSJCVUF attribute_name_index The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7) representing the string "BootstrapMethods". attribute_length The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. num_bootstrap_methods The value of the num_bootstrap_methods item determines the number of bootstrap method specifiers in the bootstrap_methods array. bootstrap_methods[] Each entry in the bootstrap_methods table contains an index to a CONSTANT_MethodHandle_info structure which specifies a bootstrap method, and a sequence (perhaps empty) of indexes to static arguments for the bootstrap method. #PPUTUSBQ.FUIPET *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 55

Slide 55 text

Constant pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #19 = Utf8 BootstrapMethods #20 = MethodHandle 6:#33 // 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; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ࿦ΑΓόΠφϦ BootstrapMethods_attribute { u2 attribute_name_index; u4 attribute_length; u2 num_bootstrap_methods; { u2 bootstrap_method_ref; u2 num_bootstrap_arguments; u2 bootstrap_arguments[num_bootstrap_arguments]; } bootstrap_methods[num_bootstrap_methods]; } 5IF#PPUTUSBQ.FUIPET"UUSJCVUF attribute_name_index The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7) representing the string "BootstrapMethods". attribute_length The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. num_bootstrap_methods The value of the num_bootstrap_methods item determines the number of bootstrap method specifiers in the bootstrap_methods array. bootstrap_methods[] Each entry in the bootstrap_methods table contains an index to a CONSTANT_MethodHandle_info structure which specifies a bootstrap method, and a sequence (perhaps empty) of indexes to static arguments for the bootstrap method. #PPUTUSBQ.FUIPET BUUSJCVUF@OBNF@JOEFY BUUSJCVUF@MFOHUI OVN@CPPUTUSBQ@NFUIPET *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 56

Slide 56 text

Constant pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #19 = Utf8 BootstrapMethods #20 = MethodHandle 6:#33 // 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; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ࿦ΑΓόΠφϦ BootstrapMethods_attribute { u2 attribute_name_index; u4 attribute_length; u2 num_bootstrap_methods; { u2 bootstrap_method_ref; u2 num_bootstrap_arguments; u2 bootstrap_arguments[num_bootstrap_arguments]; } bootstrap_methods[num_bootstrap_methods]; } 5IF#PPUTUSBQ.FUIPET"UUSJCVUF bootstrap_methods[] bootstrap_method_ref The value of the bootstrap_method_ref item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_MethodHandle_info structure (§4.4.8). The method handle will be resolved during resolution of a dynamically- computed constant or call site (§5.4.3.6), and then invoked as if by invocation of invokeWithArguments in java.lang.invoke.MethodHandle. num_bootstrap_arguments The value of the num_bootstrap_arguments item gives the number of items in the bootstrap_arguments array. bootstrap_arguments[] Each entry in the bootstrap_arguments array must be a valid index into the constant_pool table. The constant_pool entry at that index must be loadable (§4.4). #PPUTUSBQ.FUIPET CPPUTUSBQ@NFUIPE@SFG CPPUTUSBQ@BSHVNFOUT<> CPPUTUSBQ@BSHVNFOUT<> OVN@CPPUTUSBQ@NFUIPE @BSHVNFOUT *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 57

Slide 57 text

Constant pool: #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #34 = Methodref #7.#46 // invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V BootstrapMethods: 0: #20 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/ CallSite; Method arguments: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ࿦ΑΓόΠφϦ CONSTANT_MethodHandle_info { u1 tag; u1 reference_kind; u2 reference_index; } 5IF$0/45"/5@.FUIPE)BOEMF@JOGP 4USVDUVSF The CONSTANT_MethodHandle_info structure is used to represent a method handle: tag The tag item has the value CONSTANT_MethodHandle (15). reference_kind The value of the reference_kind item must be in the range 1 to 9. The value denotes the kind of this method handle, which characterizes its bytecode behavior (§5.4.3.5). reference_index The value of the reference_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be as follows: If the value of the reference_kind item is 6 (REF_invokeStatic) or 7 (REF_invokeSpecial), then if the class file version number is 52.0 or above, the constant_pool entry at that index must be either a CONSTANT_Methodref_info structure or a CONSTANT_InterfaceMethodref_info structure (§4.4.2) representing a class's or interface's method for which a method handle is to be created. .FUIPE)BOEMF$POTUBOU1PPM *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 58

Slide 58 text

Constant pool: #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #34 = Methodref #7.#46 // invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V BootstrapMethods: 0: #20 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/ CallSite; Method arguments: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ࿦ΑΓόΠφϦ .FUIPE)BOEMF$POTUBOU1PPM CONSTANT_MethodHandle_info { u1 tag; u1 reference_kind; u2 reference_index; } 5IF$0/45"/5@.FUIPE)BOEMF@JOGP 4USVDUVSF The CONSTANT_MethodHandle_info structure is used to represent a method handle: tag The tag item has the value CONSTANT_MethodHandle (15). reference_kind The value of the reference_kind item must be in the range 1 to 9. The value denotes the kind of this method handle, which characterizes its bytecode behavior (§5.4.3.5). reference_index The value of the reference_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be as follows: If the value of the reference_kind item is 6 (REF_invokeStatic) or 7 (REF_invokeSpecial), then if the class file version number is 52.0 or above, the constant_pool entry at that index must be either a CONSTANT_Methodref_info structure or a CONSTANT_InterfaceMethodref_info structure (§4.4.2) representing a class's or interface's method for which a method handle is to be created. *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 59

Slide 59 text

࿦ΑΓόΠφϦ InnerClasses_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_classes; { u2 inner_class_info_index; u2 outer_class_info_index; u2 inner_name_index; u2 inner_class_access_flags; } classes[number_of_classes]; } 5IF*OOFS$MBTTFT"UUSJCVUF *OOFS$MBTTFT attribute_name_index The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7) representing the string "InnerClasses". attribute_length The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. number_of_classes The value of the number_of_classes item indicates the number of entries in the classes array. classes[] Every CONSTANT_Class_info entry in the constant_pool table which represents a class or interface C that is not a package member must have exactly one corresponding entry in the classes array. Constant pool: #49 = Class #54 // java/lang/invoke/MethodHandles$Lookup #50 = Utf8 Lookup #51 = Utf8 InnerClasses #53 = Class #55 // java/lang/invoke/MethodHandles InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 60

Slide 60 text

Constant pool: #49 = Class #54 // java/lang/invoke/MethodHandles$Lookup #50 = Utf8 Lookup #51 = Utf8 InnerClasses #53 = Class #55 // java/lang/invoke/MethodHandles InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles ࿦ΑΓόΠφϦ InnerClasses_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_classes; { u2 inner_class_info_index; u2 outer_class_info_index; u2 inner_name_index; u2 inner_class_access_flags; } classes[number_of_classes]; } 5IF*OOFS$MBTTFT"UUSJCVUF *OOFS$MBTTFT attribute_name_index The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7) representing the string "InnerClasses". attribute_length The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. number_of_classes The value of the number_of_classes item indicates the number of entries in the classes array. classes[] Every CONSTANT_Class_info entry in the constant_pool table which represents a class or interface C that is not a package member must have exactly one corresponding entry in the classes array. ͜Ε͸ͳΜͩΖ͏🤔 BUUSJCVUF@OBNF@JOEFY JOOFS@DMBTT@JOGP@JOEFY PVUFS@DMBTT@JOGP@JOEFY JOOFS@OBNF@JOEFY JOOFS@DMBTT@BDDFTT@ fl BHT C QVCMJDTUBUJD fi OBM *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 61

Slide 61 text

Constant pool: #49 = Class #54 // java/lang/invoke/MethodHandles$Lookup #50 = Utf8 Lookup #51 = Utf8 InnerClasses #53 = Class #55 // java/lang/invoke/MethodHandles InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles ࿦ΑΓόΠφϦ InnerClasses_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_classes; { u2 inner_class_info_index; u2 outer_class_info_index; u2 inner_name_index; u2 inner_class_access_flags; } classes[number_of_classes]; } 5IF*OOFS$MBTTFT"UUSJCVUF *OOFS$MBTTFT attribute_name_index The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7) representing the string "InnerClasses". attribute_length The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. number_of_classes The value of the number_of_classes item indicates the number of entries in the classes array. classes[] Every CONSTANT_Class_info entry in the constant_pool table which represents a class or interface C that is not a package member must have exactly one corresponding entry in the classes array. BUUSJCVUF@OBNF@JOEFY JOOFS@DMBTT@JOGP@JOEFY PVUFS@DMBTT@JOGP@JOEFY If the constant pool of a class or interface C contains at least one CONSTANT_Class_info entry (§4.4.1) which represents a class or interface that is not a member of a package, then there must be exactly one InnerClasses attribute in the attributes table of the ClassFile structure for C. 1BDLBHF.FNCFSͰͳ͍$MBTT΍*OUFSGBDFͷࢀরͷࡍ͸ *OOFS$MBTTFTʹॻ͍͓ͯ͘ඞཁ͕͋Δ *OWPLF%ZOBNJD4JNQMFDMBTT *OWPLF%ZOBNJD4JNQMFKWN

Slide 62

Slide 62 text

public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #20 = MethodHandle 6:#33 // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/ CallSite; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; : } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ͭ·Γʜ *OWPLF%ZOBNJD4JNQMFKWN

Slide 63

Slide 63 text

public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #20 = MethodHandle 6:#33 // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/ CallSite; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; : } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ͭ·Γʜ ᶃJOWPLFEZOBNJD *OWPLF%ZOBNJD4JNQMFKWN

Slide 64

Slide 64 text

public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #20 = MethodHandle 6:#33 // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/ CallSite; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; : } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ͭ·Γʜ ᶄҾ਺/BNF"OE5ZQFSVO -KBWBMBOH3VOOBCMF Λऔͬͯ#PPU4USBQ.FUIPET *OWPLF%ZOBNJD4JNQMFKWN

Slide 65

Slide 65 text

public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #20 = MethodHandle 6:#33 // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/ CallSite; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; : } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #20 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; // MethodHandles.lookup() Ljava/lang/String; // “run” Ljava/lang/invoke/MethodType; // ()Ljava/lang/Runnable; Ljava/lang/invoke/MethodType; // ()V Ljava/lang/invoke/MethodHandle; // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V Ljava/lang/invoke/MethodType; // ()V )Ljava/lang/invoke/CallSite; Method arguments: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ͭ·Γʜ ᶅҾ਺Λ͔͖ूΊͯɺΦϖϥϯυελοΫʹੵΜͰ *OWPLF%ZOBNJD4JNQMFKWN

Slide 66

Slide 66 text

public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #20 = MethodHandle 6:#33 // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/ CallSite; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; : } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ͭ·Γʜ ᶆ.FUIPE)BOEMFΛΠϯελϯεԽͯ͠ɺ NIJOWPLF8JUI"SHVNFOUT Λ࣮ߦ *OWPLF%ZOBNJD4JNQMFKWN

Slide 67

Slide 67 text

public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #20 = MethodHandle 6:#33 // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/ CallSite; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; : } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ͭ·Γʜ ᶇTUBUJDNFUIPEͷ -BNCEB.FUBGBDUPSZNFUBGBDUPSZ ͕࣮ߦ͞Εɺ $BMM4JUFΛฦ͢ *OWPLF%ZOBNJD4JNQMFKWN

Slide 68

Slide 68 text

public class invoke.dynamic.InvokeDynamicSimple Constant Pool: #2 = InvokeDynamic #0:#23 // #0:run:()Ljava/lang/Runnable; #20 = MethodHandle 6:#33 // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/ CallSite; #21 = MethodType #10 // ()V #22 = MethodHandle 6:#34 // REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #23 = NameAndType #35:#36 // run:()Ljava/lang/Runnable; : public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; : } SourceFile: "InvokeDynamicSimple.java" InnerClasses: public static final #50= #49 of #53; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #20 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: #21 ()V #22 REF_invokeStatic invoke/dynamic/InvokeDynamicSimple.lambda$main$0:()V #21 ()V ͭ·Γʜ ᶈ$BMM4JUFDTHFU5BSHFUJOWPLF Λ࣮ߦ͢Δ͜ͱͰɺ໨తͷ SVO -KBWBMBOH3VOOBCMF ͷ݁ՌΛಘΔʂʂʂ *OWPLF%ZOBNJD4JNQMFKWN

Slide 69

Slide 69 text

8IBU`TJOWPLFEZOBNJD ”Ϋϥεɾϩʔμʔ͕invokedynamic໋ྩΛؚΉΫϥεΛϩʔυ͢Δͱ͖ɺϝιουݺग़͠ͷλʔήοτ͸·ͩΘ͔ͬ ͍ͯ·ͤΜɻ͜ͷઃܭ͸ɺJVMόΠτίʔυͷଞͷͲͷछྨͷίʔϧɾαΠτʢݺग़͠৔ॴʣͱ΋ҟͳΓ·͢ɻ ” ”invokedynamicͰ͸ɺ໋ྩίʔυ͕σΟεύον͞Εͨͱ͖ʹ࣮ࡍʹݺͼग़͞ΕΔϝιουΛ͸Δ͔ʹॊೈʹܾΊΔ ͜ͱ͕Ͱ͖·͢ɻinvokedynamic໋ྩίʔυ͸ɺ͜ͷॊೈੑΛ࣮ݱ͢ΔͨΊʹɺಈతݺग़͠ΛؚΉΫϥεͷఆ਺ϓʔϧ ಺ʹ͋ΔಛผͳଐੑΛࢀর͍ͯ͠·͢ɻͦͷଐੑ͸ɺϒʔτετϥοϓɾϝιουʢBSMʣͱ ݺ͹Εɺಈతݺग़͠ͷ ੑ࣭Λࢧ͑Δ௥Ճ৘ใΛؚΜͰ͍·͢ɻ ” ”invokedynamic໋ྩͷίʔϧɾαΠτ͸ɺΫϥε͕ϩʔυ͞Εͨͱ͖ʹɺ͍Θ͹ʮະ઀ଓʯͷঢ়ଶʹͳΓ·͢ɻ ࣮ࡍ ʹͲͷϝιουΛݺͼग़͢΂͖͔ΛܾΊΔͨΊʹBSM͕ݺͼग़͞ΕΔͱɺͦͷ݁ՌͰ͋ΔCallSiteΦϒδΣΫτ ͕ ίʔϧɾαΠτʹʮ઀ଓʯ͞Ε·͢ɻ ” — JavaͰͷinvokedynamicʹΑΔϝιουݺग़͠Λཧղ͢Δ

Slide 70

Slide 70 text

׬શཧղ🙌

Slide 71

Slide 71 text

͔ͤͬ͘ͳͷͰʜ -BNCEB͸ͲͷΑ͏ʹ࣮૷͞Ε͍ͯΔ͔ʁ public class invoke.dynamic.InvokeDynamicComplicated Constant pool: #4 = InvokeDynamic #0:#27 // #0:apply:(J)Ljava/util/function/Function; #23 = MethodHandle 6:#37 // REF_invokeStatic java/lang/invoke/ LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/CallSite; #24 = MethodType #38 // (Ljava/lang/Object;)Ljava/lang/Object; #25 = MethodHandle 6:#39 // REF_invokeStatic invoke/dynamic/ InvokeDynamicComplicated.lambda$main$0:(JLjava/lang/Integer;)Ljava/lang/Double; #26 = MethodType #40 // (Ljava/lang/Integer;)Ljava/lang/Double; #27 = NameAndType #41:#42 // apply:(J)Ljava/util/function/Function; { public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: ldc2_w #2 // long 10l 3: lstore_1 4: lload_1 5: invokedynamic #4, 0 // InvokeDynamic #0:apply:(J)Ljava/util/ function/Function; } BootstrapMethods: 0: #23 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: #24 (Ljava/lang/Object;)Ljava/lang/Object; #25 REF_invokeStatic invoke/dynamic/InvokeDynamicComplicated.lambda$main$0:(JLjava/ lang/Integer;)Ljava/lang/Double; #26 (Ljava/lang/Integer;)Ljava/lang/Double; package invoke.dynamic; import java.util.function.Function; public class InvokeDynamicComplicated { public static void main(String[] args) { long l = 10L; Function f = (i) -> (double)i / (double)l; f.apply(1); } } *OWPLF%ZOBNJD$PNQMJDBUFEKBWB *OWPLF%ZOBNJD$PNQMJDBUFEKWN w ͍ΘΏΔؔ਺ܕ*OUFSGBDF w *OWPLF%ZOBNJDʹͳ͕ͬͨɺҾ਺͕ੜ͑ͨ w JMͷܭࢉ͸Ͳ͜΁ߦͬͨ BQQMZ͕JOUͰ͸ͳ͘ɺ MPOHҾ਺Λऔ͍ͬͯΔ

Slide 72

Slide 72 text

ͪΐͬͱ·ͬͯ🤔 w *OWPLFEZOBNJDͷ.FUIPE)BOEMFҾ਺͸͓ͦΒ͘ΫϩʔδϟͩΖ͏ w ͔͍͘͠͠ΒͳΜͰ΋ɺόΠφϦʹଘࡏ͠ͳ͍ϝιουΛੜ੒Ͱ͖Δ͸͕ͣͳ ͍ɻͲ͏ͳ͍ͬͯΔͷ͔ʁ w όΠφϦϑΝΠϧΛ೷͍ͯΈΔͱɺͲ͏΋EEJW %JWJEF%PVCMFY' ͕ଘࡏ ͍ͯ͠Δʜ

Slide 73

Slide 73 text

ͪΐͬͱ·ͬͯ🤔 w *OWPLFEZOBNJDͷ.FUIPE)BOEMFҾ਺͸͓ͦΒ͘ΫϩʔδϟͩΖ͏ w ͔͍͘͠͠ΒͳΜͰ΋ɺόΠφϦʹଘࡏ͠ͳ͍ϝιουΛੜ੒Ͱ͖Δ͸͕ͣͳ ͍ɻͲ͏ͳ͍ͬͯΔͷ͔ʁ w όΠφϦϑΝΠϧΛ೷͍ͯΈΔͱɺͲ͏΋EEJW %JWJEF%PVCMFY' ͕ଘࡏ ͍ͯ͠Δʜ EEJW JOWPLFTUBUJD KBWBMBOH%PVCMFWBMVF0G % -KBWBMBOH%PVCMF

Slide 74

Slide 74 text

λω໌͔͠ w -BNCEBͷ࣮ଶ͸ɺQSJWBUFTUBUJDNFUIPEͱͯ͠$MBTT'JMFʹଘࡏ͢Δʂ w ίϯύΠϥ͕MBNCEBຊମΛQSJWBUFTUBUJDͱͯ͠࿉੒ͨ͠ w Ͱ͸#4.͸͜ͷϝιουͷࢀরΛฦ٫͍ͯ͠Δͷ͔ʁ w ͔͠͠ɺҾ਺͕ҟͳΔʜ private static java.lang.Double lambda$main$0(long, java.lang.Integer); descriptor: (JLjava/lang/Integer;)Ljava/lang/Double; flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC Code: stack=4, locals=3, args_size=2 0: aload_2 1: invokevirtual #7 // Method java/lang/Integer.intValue:()I 4: i2d 5: lload_0 6: l2d 7: ddiv 8: invokestatic #8 // Method java/lang/Double.valueOf: (D)Ljava/lang/Double; 11: areturn LineNumberTable: line 8: 0 ❯ javac InvokeDynamicComplecated.java ❯ javap -v -p —s -constants InvokeDynamicComplecated.class > InvokeDynamicComplecatedWithPrivate.jvm *OWPLF%ZOBNJD$PNQMJDBUFE8JUI1SJWBUFKWN QŠQSJWBUFPQUJPO͕ඞཁ package invoke.dynamic; import java.util.function.Function; public class InvokeDynamicComplicated { public static void main(String[] args) { long l = 10L; Function f = (i) -> (double)i / (double)l; f.apply(1); } } *OWPLF%ZOBNJD$PNQMJDBUFEKBWB

Slide 75

Slide 75 text

΋͏Ұ౓#4.ΛݟͯΈΔ w -BNCEB.FUBGBDUPSZNFUBGBDUPSZ Λ࣮ߦ͍ͯ͠Δ w Ҿ਺͸ઌͷઆ໌͔Βɺ͜Μͳ͔Μ͕ͩ͡ʜ public class invoke.dynamic.InvokeDynamicComplicated Constant pool: #4 = InvokeDynamic #0:#27 // #0:apply:(J)Ljava/util/function/Function; #23 = MethodHandle 6:#37 // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/CallSite; #24 = MethodType #38 // (Ljava/lang/Object;)Ljava/lang/Object; #25 = MethodHandle 6:#39 // REF_invokeStatic invoke/dynamic/InvokeDynamicComplicated.lambda$main$0:(JLjava/lang/Integer;)Ljava/lang/Double; #26 = MethodType #40 // (Ljava/lang/Integer;)Ljava/lang/Double; #27 = NameAndType #41:#42 // apply:(J)Ljava/util/function/Function; } BootstrapMethods: 0: #23 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; // MethodHandles.lookup() Ljava/lang/String; // apply Ljava/lang/invoke/MethodType; // (J)Ljava/util/function/Function; Ljava/lang/invoke/MethodType; // (Ljava/lang/Object;)Ljava/lang/Object; Ljava/lang/invoke/MethodHandle; // InvokeDynamicComplicated.lambda$main$0:(JLjava/lang/Integer;)Ljava/lang/Double; Ljava/lang/invoke/MethodType; // (Ljava/lang/Integer;)Ljava/lang/Double; )Ljava/lang/invoke/CallSite; Method arguments: #24 (Ljava/lang/Object;)Ljava/lang/Object; #25 REF_invokeStatic invoke/dynamic/InvokeDynamicComplicated.lambda$main$0:(JLjava/lang/Integer;)Ljava/lang/Double; #26 (Ljava/lang/Integer;)Ljava/lang/Double;

Slide 76

Slide 76 text

΋͏Ұ౓#4.ΛݟͯΈΔ w -BNCEB.FUBGBDUPSZNFUBGBDUPSZ Λ࣮ߦ͍ͯ͠Δ w Ҿ਺͸ઌͷઆ໌͔Βɺ͜Μͳ͔Μ͕ͩ͡ʜ public class invoke.dynamic.InvokeDynamicComplicated Constant pool: #4 = InvokeDynamic #0:#27 // #0:apply:(J)Ljava/util/function/Function; #23 = MethodHandle 6:#37 // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(…)Ljava/lang/invoke/CallSite; #24 = MethodType #38 // (Ljava/lang/Object;)Ljava/lang/Object; #25 = MethodHandle 6:#39 // REF_invokeStatic invoke/dynamic/InvokeDynamicComplicated.lambda$main$0:(JLjava/lang/Integer;)Ljava/lang/Double; #26 = MethodType #40 // (Ljava/lang/Integer;)Ljava/lang/Double; #27 = NameAndType #41:#42 // apply:(J)Ljava/util/function/Function; } BootstrapMethods: 0: #23 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; // MethodHandles.lookup() Ljava/lang/String; // apply Ljava/lang/invoke/MethodType; // (J)Ljava/util/function/Function; Ljava/lang/invoke/MethodType; // (Ljava/lang/Object;)Ljava/lang/Object; Ljava/lang/invoke/MethodHandle; // InvokeDynamicComplicated.lambda$main$0:(JLjava/lang/Integer;)Ljava/lang/Double; Ljava/lang/invoke/MethodType; // (Ljava/lang/Integer;)Ljava/lang/Double; )Ljava/lang/invoke/CallSite; Method arguments: #24 (Ljava/lang/Object;)Ljava/lang/Object; #25 REF_invokeStatic invoke/dynamic/InvokeDynamicComplicated.lambda$main$0:(JLjava/lang/Integer;)Ljava/lang/Double; #26 (Ljava/lang/Integer;)Ljava/lang/Double; ୭ʁ ίϯύΠϥ͕࿉੒ͨ͠MBNCEBຊମɹ MPOH *OUFHFS %PVCMF ίʔυ্ͷMBNCEBͷܕ *OUFHFS %PVCMF

Slide 77

Slide 77 text

-BNCEB.FUBGBDUPSZͷ࣮૷Λ֬ೝ͢Δ public static CallSite metafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType) throws LambdaConversionException { AbstractValidatingLambdaMetafactory mf; mf = new InnerClassLambdaMetafactory(caller, invokedType, invokedName, samMethodType, implMethod, instantiatedMethodType, false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY); mf.validateMetafactoryArgs(); return mf.buildCallSite(); } -BNCEB.FUBGBDUPSZKBWB w *OOFS$MBTT-BNCEB.FUBGBDUPSZΛ࣮ߦ͍ͯ͠Δ w *OWPLFE TBN JNQM🤔

Slide 78

Slide 78 text

4JOHMF"CTUSBDU.FUIPE4". /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { } abstract class AbstractValidatingLambdaMetafactory { /* * For context, the comments for the following fields are marked in quotes * with their values, given this program: * interface II { Object foo(T x); } * interface JJ extends II { } * class CC { String impl(int i) { return "impl:"+i; }} * class X { * public static void main(String[] args) { * JJ iii = (new CC())::impl; * System.out.printf(">>> %s\n", iii.foo(44)); * }} */ final Class> targetClass; // The class calling the meta-factory via invokedynamic "class X" final MethodType invokedType; // The type of the invoked method "(CC)II" final Class> samBase; // The type of the returned instance "interface JJ" final String samMethodName; // Name of the SAM method "foo" final MethodType samMethodType; // Type of the SAM method "(Object)Object" final MethodHandle implMethod; // Raw method handle for the implementation method final MethodType implMethodType; // Type of the implMethod MethodHandle "(CC,int)String" w 4".4JOHMF"CTUSBDU.FUIPE w ͜͜Ͱ΍͍ͬͯΔͷ͸͍ΘΏΔl4".ม׵z "CTUSBDU7BMJEBUJOH-BNCEB.FUBGBDUPSZKBWB

Slide 79

Slide 79 text

4JOHMF"CTUSBDU.FUIPE4". /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { } abstract class AbstractValidatingLambdaMetafactory { /* * For context, the comments for the following fields are marked in quotes * with their values, given this program: * interface II { Object foo(T x); } * interface JJ extends II { } * class CC { String impl(int i) { return "impl:"+i; }} * class X { * public static void main(String[] args) { * JJ iii = (new CC())::impl; * System.out.printf(">>> %s\n", iii.foo(44)); * }} */ final Class> targetClass; // The class calling the meta-factory via invokedynamic "class X" final MethodType invokedType; // The type of the invoked method "(CC)II" final Class> samBase; // The type of the returned instance "interface JJ" final String samMethodName; // Name of the SAM method "foo" final MethodType samMethodType; // Type of the SAM method "(Object)Object" final MethodHandle implMethod; // Raw method handle for the implementation method final MethodType implMethodType; // Type of the implMethod MethodHandle "(CC,int)String" ͜͜Ͱ࣮ߦ͞ΕΔϝιου͸ɺ$$ΛҾ਺ʹͱͬͯ**Λฦ͢΋ͷͱΈͳͤΔ 4JOHMF"CTUSBDU.FUIPE ࣮૷͞Εͨϝιου w 4".4JOHMF"CTUSBDU.FUIPE w ͜͜Ͱ΍͍ͬͯΔͷ͸͍ΘΏΔl4".ม׵z "CTUSBDU7BMJEBUJOH-BNCEB.FUBGBDUPSZKBWB

Slide 80

Slide 80 text

ࠓͷίϯςΩετͰ͸ public static CallSite metafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType) throws LambdaConversionException { } package invoke.dynamic; import java.util.function.Function; public class InvokeDynamicComplicated { public static void main(String[] args) { long l = 10L; Function f = (i) -> (double)i / (double)l; f.apply(1); } } @FunctionalInterface public interface Function { R apply(T t); -BNCEB.FUBGBDUPSZKBWB 0: #23 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; // MethodHandles.lookup() Ljava/lang/String; // apply Ljava/lang/invoke/MethodType; // (J)Ljava/util/function/Function; Ljava/lang/invoke/MethodType; // (Ljava/lang/Object;)Ljava/lang/Object; Ljava/lang/invoke/MethodHandle; // InvokeDynamicComplicated.lambda$main$0: (JLjava/lang/Integer;)Ljava/lang/Double; Ljava/lang/invoke/MethodType; // (Ljava/lang/Integer;)Ljava/lang/Double; )Ljava/lang/invoke/CallSite; w ͜͜Ͱى͜Δ΂͖ݱ৅͸ʜ w 'VODUJPO*OUFSGBDFΛ࣮૷ͨ͠Πϯελϯε͕ฦ͞ΕΔ͜ͱ

Slide 81

Slide 81 text

ࠓͷίϯςΩετͰ͸ public static CallSite metafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType) throws LambdaConversionException { } -BNCEB.FUBGBDUPSZKBWB package invoke.dynamic; import java.util.function.Function; public class InvokeDynamicComplicated { public static void main(String[] args) { long l = 10L; Function f = (i) -> (double)i / (double)l; f.apply(1); } } *OWPLF%ZOBNJD$PNQMJDBUFEKBWB @FunctionalInterface public interface Function { R apply(T t); 0: #23 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; // MethodHandles.lookup() Ljava/lang/String; // apply Ljava/lang/invoke/MethodType; // (J)Ljava/util/function/Function; Ljava/lang/invoke/MethodType; // (Ljava/lang/Object;)Ljava/lang/Object; Ljava/lang/invoke/MethodHandle; // InvokeDynamicComplicated.lambda$main$0: (JLjava/lang/Integer;)Ljava/lang/Double; Ljava/lang/invoke/MethodType; // (Ljava/lang/Integer;)Ljava/lang/Double; )Ljava/lang/invoke/CallSite; w DBMMFS+7.͕࿉੒ͨ͠.FUIPE)BOEMFT-PPLVQ w JOWPLFE/BNF࣮ߦ͞Ε͍ͯΔϝιουͷ໊લɻ4".ϝιου໊͔ΒऔΒΕΔ w JOWPLFE5ZQF࣮ߦ͞Ε͍ͯΔܕɻ4".*OUFSGBDFͷΠϯελϯεΛฦ͢ w TBN.FUIPE5ZQFΦϦδφϧͷ4".ϝιουͷܕɻܕফڈʹΑΓδΣωϦΫεܕ͕མͪɺ 0CKFDU 0CKFDUʹͳΔ w JNQM.FUIPEMBNCEB࣮૷ຊମ΁ͷࢀর w JOTUBODJBUFE.FUIPE5ZQFΠϯελϯεԽ͞Εͨ͋ͱͷBQQMZϝιουͷܕɻΦϦδφϧͷMBNCEB࣮૷ͱಉҰ

Slide 82

Slide 82 text

5JQT#4.ɺσόοάͰ͖Δ w ౰વͱ͍͑͹ͱ͏ͥΜͳΜͰ͕͢ʜ w ׬શཧղʹΊͪΌศར

Slide 83

Slide 83 text

*OOFS$MBTT-BNCEB.FUBGBDUPSZͷ࣮૷ public static CallSite metafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType) throws LambdaConversionException { AbstractValidatingLambdaMetafactory mf; mf = new InnerClassLambdaMetafactory(caller, invokedType, invokedName, samMethodType, implMethod, instantiatedMethodType, false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY); mf.validateMetafactoryArgs(); return mf.buildCallSite(); } CallSite buildCallSite() throws LambdaConversionException { final Class> innerClass = spinInnerClass(); if (invokedType.parameterCount() == 0 && !disableEagerInitialization) { // In the case of a non-capturing lambda, we optimize linkage by pre-computing a single instance, // unless we've suppressed eager initialization final Constructor>[] ctrs = AccessController.doPrivileged( new PrivilegedAction<>() { @Override public Constructor>[] run() { Constructor>[] ctrs = innerClass.getDeclaredConstructors(); if (ctrs.length == 1) { // The lambda implementing inner class constructor is private, set // it accessible (by us) before creating the constant sole instance ctrs[0].setAccessible(true); } return ctrs; } }); if (ctrs.length != 1) { throw new LambdaConversionException("Expected one lambda constructor for " + innerClass.getCanonicalName() + ", got " + ctrs.length); } try { Object inst = ctrs[0].newInstance(); return new ConstantCallSite(MethodHandles.constant(samBase, inst)); } catch (ReflectiveOperationException e) { throw new LambdaConversionException("Exception instantiating lambda object", e); } } else { try { if (!disableEagerInitialization) { UNSAFE.ensureClassInitialized(innerClass); } return new ConstantCallSite( MethodHandles.Lookup.IMPL_LOOKUP .findStatic(innerClass, NAME_FACTORY, invokedType)); } catch (ReflectiveOperationException e) { throw new LambdaConversionException("Exception finding constructor", e); } } } w *OOFS$MBTT-BNCEB'BDUPSZΛੜ੒ w CVJME$BMM4JUFͰ$BMM4JUFΛ࡞੒ͯ͠ฦ͢ w CVJME$BMM4JUF w TQJOO*OFS$MBTT ͰΫϥεΛੜ੒͍ͯ͠Δ

Slide 84

Slide 84 text

*OOFS$MBTT-BNCEB.FUBGBDUPSZͷ࣮૷ public static CallSite metafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType) throws LambdaConversionException { AbstractValidatingLambdaMetafactory mf; mf = new InnerClassLambdaMetafactory(caller, invokedType, invokedName, samMethodType, implMethod, instantiatedMethodType, false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY); mf.validateMetafactoryArgs(); return mf.buildCallSite(); } CallSite buildCallSite() throws LambdaConversionException { final Class> innerClass = spinInnerClass(); if (invokedType.parameterCount() == 0 && !disableEagerInitialization) { // In the case of a non-capturing lambda, we optimize linkage by pre-computing a single instance, // unless we've suppressed eager initialization final Constructor>[] ctrs = AccessController.doPrivileged( new PrivilegedAction<>() { @Override public Constructor>[] run() { Constructor>[] ctrs = innerClass.getDeclaredConstructors(); if (ctrs.length == 1) { // The lambda implementing inner class constructor is private, set // it accessible (by us) before creating the constant sole instance ctrs[0].setAccessible(true); } return ctrs; } }); if (ctrs.length != 1) { throw new LambdaConversionException("Expected one lambda constructor for " + innerClass.getCanonicalName() + ", got " + ctrs.length); } try { Object inst = ctrs[0].newInstance(); return new ConstantCallSite(MethodHandles.constant(samBase, inst)); } catch (ReflectiveOperationException e) { throw new LambdaConversionException("Exception instantiating lambda object", e); } } else { try { if (!disableEagerInitialization) { UNSAFE.ensureClassInitialized(innerClass); } return new ConstantCallSite( MethodHandles.Lookup.IMPL_LOOKUP .findStatic(innerClass, NAME_FACTORY, invokedType)); } catch (ReflectiveOperationException e) { throw new LambdaConversionException("Exception finding constructor", e); } } } w TQJOO*OFS$MBTT Ͱੜ੒ͨ͠Ϋϥε͕ʜ w Ҿ਺ͳ͠ w γϯάϧτϯΛੜ੒ɺݻఆ஋ͱͯ͠ฦ͢ w Ҿ਺͋ΓʢΫϩʔδϟ͋Γʣ w ϑΝΫτϦϝιου /".&@'"$503: Λόϯυϧ

Slide 85

Slide 85 text

private Class> spinInnerClass() throws LambdaConversionException { String[] interfaces; String samIntf = samBase.getName().replace('.', '/'); boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase); if (markerInterfaces.length == 0) { interfaces = new String[]{samIntf}; } else { : cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC, lambdaClassName, null, JAVA_LANG_OBJECT, interfaces); // Generate final fields to be filled in by constructor for (int i = 0; i < argDescs.length; i++) { FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argDescs[i], null, null); fv.visitEnd(); } generateConstructor(); if (invokedType.parameterCount() != 0 || disableEagerInitialization) { generateFactory(); } // Forward the SAM method MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName, samMethodType.toMethodDescriptorString(), null, null); mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); new ForwardingMethodGenerator(mv).generate(samMethodType); : cw.visitEnd(); // Define the generated class in this VM. final byte[] classBytes = cw.toByteArray(); : return UNSAFE.defineAnonymousClass(targetClass, classBytes, null); } w $MBTT8SJUFSΛར༻ͯ͠ɺҎԼͷόΠφϦΛੜ੒͢Δ w 4".ͷJOUFSGBDFΛJNQMFNFOUͨ͠*OOFS$MBTT w AQSJWBUFDMBTT0VUFS$MBTT-BNCEB/ JNQMFNFOUT4".*OUFSGBDFA w ͦͷίϯετϥΫλ w ʢίϯετϥΫλύϥϝλ͕͋ΔΫϩʔδϟ͕͋ Δ৔߹ʣΠϯελϯεΛ࡞ΔͨΊͷ GBDUPSZNFUIPEAQSJWBUFTUBUJD fi OBM HFU-BNCEBA w ίϯετϥΫλύϥϝλ͕͋Δ৔߹ɺͦΕΛ֨ೲ͢Δϑ Οʔϧυ w 4".ΠϯλʔϑΣʔε༻ͷϝιου w ࣮ߦͨ͠ࡍɺMBNCEBຊମʢQSJWBUFTUBUJD NBJOMBNCEB Λ࣮ߦ͢Δ w Ϋϥεϩʔμʹొ࿥ʂ TQJO*OOFS$MBTT ͷ࣮૷

Slide 86

Slide 86 text

private Class> spinInnerClass() throws LambdaConversionException { String[] interfaces; String samIntf = samBase.getName().replace('.', '/'); boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase); if (markerInterfaces.length == 0) { interfaces = new String[]{samIntf}; } else { : cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC, lambdaClassName, null, JAVA_LANG_OBJECT, interfaces); // Generate final fields to be filled in by constructor for (int i = 0; i < argDescs.length; i++) { FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argDescs[i], null, null); fv.visitEnd(); } generateConstructor(); if (invokedType.parameterCount() != 0 || disableEagerInitialization) { generateFactory(); } // Forward the SAM method MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName, samMethodType.toMethodDescriptorString(), null, null); mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); new ForwardingMethodGenerator(mv).generate(samMethodType); : cw.visitEnd(); // Define the generated class in this VM. final byte[] classBytes = cw.toByteArray(); : return UNSAFE.defineAnonymousClass(targetClass, classBytes, null); } w $MBTT8SJUFSΛར༻ͯ͠ɺҎԼͷόΠφϦΛੜ੒͢Δ w 4".ͷJOUFSGBDFΛJNQMFNFOUͨ͠*OOFS$MBTT w AQSJWBUFDMBTT0VUFS$MBTT-BNCEB/ JNQMFNFOUT4".*OUFSGBDFA w ͦͷίϯετϥΫλ w ʢίϯετϥΫλύϥϝλ͕͋ΔΫϩʔδϟ͕͋ Δ৔߹ʣΠϯελϯεΛ࡞ΔͨΊͷ GBDUPSZNFUIPEAQSJWBUFTUBUJD fi OBM HFU-BNCEBA w ίϯετϥΫλύϥϝλ͕͋Δ৔߹ɺͦΕΛ֨ೲ͢Δϑ Οʔϧυ w 4".ΠϯλʔϑΣʔε༻ͷϝιου w ࣮ߦͨ͠ࡍɺMBNCEBຊମʢQSJWBUFTUBUJD NBJOMBNCEB Λ࣮ߦ͢Δ w Ϋϥεϩʔμʹొ࿥ʂ TQJO*OOFS$MBTT ͷ࣮૷

Slide 87

Slide 87 text

private void generateConstructor() { // Generate constructor MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, constructorType.toMethodDescriptorString(), null, null); ctor.visitCode(); ctor.visitVarInsn(ALOAD, 0); ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR, METHOD_DESCRIPTOR_VOID, false); int parameterCount = invokedType.parameterCount(); for (int i = 0, lvIndex = 0; i < parameterCount; i++) { ctor.visitVarInsn(ALOAD, 0); Class> argType = invokedType.parameterType(i); ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1); lvIndex += getParameterSize(argType); ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]); } ctor.visitInsn(RETURN); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored ctor.visitMaxs(-1, -1); ctor.visitEnd(); } w ίϯετϥΫλϝιουΛੜ੒ w ҎԼͷΠϯετϥΫγϣϯΛੜ੒ w 4VQFSDMBTT KBWBMBOH0CKFDU ͷί ϯετϥΫλΛJOWPLFTUBUJDͰ࣮ߦ w Ҿ਺ʢʹΫϩʔδϟม਺ͷ਺ʣͩ ͚ɺϑΟʔϧυม਺΁ϩʔυ TQJO*OOFS$MBTT ͷ࣮૷ HFOFSBUF$POTUSVDUPS

Slide 88

Slide 88 text

private void generateConstructor() { // Generate constructor MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, constructorType.toMethodDescriptorString(), null, null); ctor.visitCode(); ctor.visitVarInsn(ALOAD, 0); ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR, METHOD_DESCRIPTOR_VOID, false); int parameterCount = invokedType.parameterCount(); for (int i = 0, lvIndex = 0; i < parameterCount; i++) { ctor.visitVarInsn(ALOAD, 0); Class> argType = invokedType.parameterType(i); ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1); lvIndex += getParameterSize(argType); ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]); } ctor.visitInsn(RETURN); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored ctor.visitMaxs(-1, -1); ctor.visitEnd(); } w ίϯετϥΫλϝιουΛੜ੒ w ҎԼͷΠϯετϥΫγϣϯΛੜ੒ w 4VQFSDMBTT KBWBMBOH0CKFDU ͷί ϯετϥΫλΛJOWPLFTUBUJDͰ࣮ߦ w Ҿ਺ʢʹΫϩʔδϟม਺ͷ਺ʣͩ ͚ɺϑΟʔϧυม਺΁ϩʔυ TQJO*OOFS$MBTT ͷ࣮૷ HFOFSBUF$POTUSVDUPS

Slide 89

Slide 89 text

private void generateFactory() { MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null); m.visitCode(); m.visitTypeInsn(NEW, lambdaClassName); m.visitInsn(Opcodes.DUP); int parameterCount = invokedType.parameterCount(); for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) { Class> argType = invokedType.parameterType(typeIndex); m.visitVarInsn(getLoadOpcode(argType), varIndex); varIndex += getParameterSize(argType); } m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false); m.visitInsn(ARETURN); m.visitMaxs(-1, -1); m.visitEnd(); } TQJO*OOFS$MBTT ͷ࣮૷ HFOFSBUF'BDUPSZ w ϑΝΫτϦϝιουΛੜ੒ w ϝιου໊ /".&@'"$503:HFU-BNCEB w ҎԼͷΠϯετϥΫγϣϯΛੜ੒ w ΠϯελϯεԽ w Ҿ਺ʢϩʔΧϧม਺ʣΛΦϖϥϯυʹϩʔυ w ίϯετϥΫλΛJOWPLFTQFDJBMͰ࣮ߦ

Slide 90

Slide 90 text

private void generateFactory() { MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null); m.visitCode(); m.visitTypeInsn(NEW, lambdaClassName); m.visitInsn(Opcodes.DUP); int parameterCount = invokedType.parameterCount(); for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) { Class> argType = invokedType.parameterType(typeIndex); m.visitVarInsn(getLoadOpcode(argType), varIndex); varIndex += getParameterSize(argType); } m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false); m.visitInsn(ARETURN); m.visitMaxs(-1, -1); m.visitEnd(); } w ϑΝΫτϦϝιουΛੜ੒ w ϝιου໊ /".&@'"$503:HFU-BNCEB w ҎԼͷΠϯετϥΫγϣϯΛੜ੒ w ΠϯελϯεԽ w Ҿ਺ʢϩʔΧϧม਺ʣΛΦϖϥϯυʹϩʔυ w ίϯετϥΫλΛJOWPLFTQFDJBMͰ࣮ߦ TQJO*OOFS$MBTT ͷ࣮૷ HFOFSBUF'BDUPSZ

Slide 91

Slide 91 text

void generate(MethodType methodType) { visitCode(); if (implKind == MethodHandleInfo.REF_newInvokeSpecial) { visitTypeInsn(NEW, implMethodClassName); visitInsn(DUP); } for (int i = 0; i < argNames.length; i++) { visitVarInsn(ALOAD, 0); visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]); } convertArgumentTypes(methodType); // Invoke the method we want to forward to visitMethodInsn(invocationOpcode(), implMethodClassName, implMethodName, implMethodDesc, implClass.isInterface()); // Convert the return value (if any) and return it // Note: if adapting from non-void to void, the 'return' // instruction will pop the unneeded result Class> implReturnClass = implMethodType.returnType(); Class> samReturnClass = methodType.returnType(); convertType(implReturnClass, samReturnClass, samReturnClass); visitInsn(getReturnOpcode(samReturnClass)); // Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored visitMaxs(-1, -1); visitEnd(); } w 4".ͷ࣮૷Λੜ੒ w ͜͜Ͱ͸BQQMZ JOU w ҎԼͷΠϯετϥΫγϣϯΛੜ੒ w -BNCEB'PSN)JEEFOΞϊςʔγϣϯΛ෇༩ w 4UBDL5SBDFʹදࣔ͞Εͳ͍ w ϑΟʔϧυBSH/͔Β஋Λϩʔυ w ίϯετϥΫλҾ਺Ͱ౉͞Εͨ஋Ϋϩʔδϟ w Ҿ਺ʢϩʔΧϧม਺ʣΛΦϖϥϯυελοΫʹϩʔ υ w 4".ͱ-BNCEBຊମͷҾ਺ܕͷҧ͍ΛνΣοΫ w JOWPLFTUBUJDͰ-BNCEBຊମϝιουΛ࣮ߦʂʂ TQJO*OOFS$MBTT ͷ࣮૷ 'PSXBSEJOH.FUIPE(FOFSBUPSHFOFSBUF // Forward the SAM method MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName, samMethodType.toMethodDescriptorString(), null, null); mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); new ForwardingMethodGenerator(mv).generate(samMethodType);

Slide 92

Slide 92 text

void generate(MethodType methodType) { visitCode(); if (implKind == MethodHandleInfo.REF_newInvokeSpecial) { visitTypeInsn(NEW, implMethodClassName); visitInsn(DUP); } for (int i = 0; i < argNames.length; i++) { visitVarInsn(ALOAD, 0); visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]); } convertArgumentTypes(methodType); // Invoke the method we want to forward to visitMethodInsn(invocationOpcode(), implMethodClassName, implMethodName, implMethodDesc, implClass.isInterface()); // Convert the return value (if any) and return it // Note: if adapting from non-void to void, the 'return' // instruction will pop the unneeded result Class> implReturnClass = implMethodType.returnType(); Class> samReturnClass = methodType.returnType(); convertType(implReturnClass, samReturnClass, samReturnClass); visitInsn(getReturnOpcode(samReturnClass)); // Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored visitMaxs(-1, -1); visitEnd(); } TQJO*OOFS$MBTT ͷ࣮૷ 'PSXBSEJOH.FUIPE(FOFSBUPSHFOFSBUF // Forward the SAM method MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName, samMethodType.toMethodDescriptorString(), null, null); mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); new ForwardingMethodGenerator(mv).generate(samMethodType); w 4".ͷ࣮૷Λੜ੒ w ͜͜Ͱ͸BQQMZ JOU w ҎԼͷΠϯετϥΫγϣϯΛੜ੒ w -BNCEB'PSN)JEEFOΞϊςʔγϣϯΛ෇༩ w 4UBDL5SBDFʹදࣔ͞Εͳ͍ w ϑΟʔϧυBSH/͔Β஋Λϩʔυ w ίϯετϥΫλҾ਺Ͱ౉͞Εͨ஋Ϋϩʔδϟ w Ҿ਺ʢϩʔΧϧม਺ʣΛΦϖϥϯυελοΫʹϩʔ υ w 4".ͱ-BNCEBຊମͷҾ਺ܕͷҧ͍ΛνΣοΫ w JOWPLFTUBUJDͰ-BNCEBຊମϝιουΛ࣮ߦʂʂ

Slide 93

Slide 93 text

5JQT#4.͕࡞੒͢Δ$MBTTΛϑΝΠϧʹు͘ .FDIBOJTNUPEVNQHFOFSBUFEMBNCEB DMBTTFTMPHMBNCEBDPEFHFOFSBUJPO // For dumping generated classes to disk, for debugging purposes private static final ProxyClassesDumper dumper; static { final String dumpProxyClassesKey = "jdk.internal.lambda.dumpProxyClasses"; String dumpPath = GetPropertyAction.privilegedGetProperty(dumpProxyClassesKey); dumper = (null == dumpPath) ? null : ProxyClassesDumper.getInstance(dumpPath); : private Class> spinInnerClass() throws LambdaConversionException { : if (dumper != null) { AccessController.doPrivileged(new PrivilegedAction<>() { @Override public Void run() { dumper.dumpClass(lambdaClassName, classBytes); return null; } }, null, new FilePermission("<>", "read, write"), // createDirectories may need it new PropertyPermission("user.dir", "read")); } *OOFS$MBTT-BNCEB.FUBGBDUPSZKBWB ❯ java -Djdk.internal.lambda.dumpProxyClasses=./ InvokeDynamicComplicated ❯ javap -v -p -s -constants 'InvokeDynamicComplicated$$Lambda$1.class' w KELJOUFSOBMMBNCEBEVNQ1SP YZ$MBTTFTΦϓγϣϯͰࢦఆͨ͠ σΟϨΫτϦʹɺ *OOFS$MBTT-BNCEB.FUBGBDUPSZ ͕ੜ੒͢ΔΫϥεΛϑΝΠϧʹు͘ w +BWBίϚϯυ࣮ߦޙʹϑΝΠϧ ͕ੜ੒͞ΕΔ

Slide 94

Slide 94 text

5JQT#4.͕࡞੒͢Δ$MBTTΛϑΝΠϧʹు͘ final class InvokeDynamicComplicated$$Lambda$1 implements java.util.function.Function : flags: (0x1030) ACC_FINAL, ACC_SUPER, ACC_SYNTHETIC { private final long arg$1; descriptor: J flags: (0x0012) ACC_PRIVATE, ACC_FINAL private InvokeDynamicComplicated$$Lambda$1(long); descriptor: (J)V flags: (0x0002) ACC_PRIVATE Code: stack=3, locals=3, args_size=2 0: aload_0 1: invokespecial #13 // Method java/lang/ Object."":()V 4: aload_0 5: lload_1 6: putfield #15 // Field arg$1:J 9: return } த਎Λ೷͍ͯΈΔ w 'VODJUPO*OUFSGBDFΛ࣮૷ͨ͠ fi OBMDMBTT w MPOHBSHϑΟʔϧυ w MPOHҾ਺ΛऔΔQSJWBUFDPOTUSVDUPS w Ҿ਺MPOHΛϑΟʔϧυBSHʹηοτ͢ Δ ACC_SUPER The ACC_SUPER flag exists for backward compatibility with code compiled by older compilers for the Java programming language. In JDK releases prior to 1.0.2, the compiler generated access_flags in which the flag now representing ACC_SUPER had no assigned meaning, and Oracle's Java Virtual Machine implementation ignored the flag if it was set. ACC_SYNTHETIC The ACC_SYNTHETIC flag indicates that this class or interface was generated by a compiler and does not appear in source code. Table 4.1-B. Class access and property modifiers *OWPLF%ZOBNJD$PNQMJDBUFE-BNCEBKBWB

Slide 95

Slide 95 text

5JQT#4.͕࡞੒͢Δ$MBTTΛϑΝΠϧʹు͘ final class InvokeDynamicComplicated$$Lambda$1 implements java.util.function.Function : flags: (0x1030) ACC_FINAL, ACC_SUPER, ACC_SYNTHETIC { private final long arg$1; descriptor: J flags: (0x0012) ACC_PRIVATE, ACC_FINAL private InvokeDynamicComplicated$$Lambda$1(long); descriptor: (J)V flags: (0x0002) ACC_PRIVATE Code: stack=3, locals=3, args_size=2 0: aload_0 1: invokespecial #13 // Method java/lang/ Object."":()V 4: aload_0 5: lload_1 6: putfield #15 // Field arg$1:J 9: return } த਎Λ೷͍ͯΈΔ w 'VODJUPO*OUFSGBDFΛ࣮૷ͨ͠ fi OBMDMBTT w MPOHBSHϑΟʔϧυ w MPOHҾ਺ΛऔΔQSJWBUFDPOTUSVDUPS w Ҿ਺MPOHΛϑΟʔϧυBSHʹηοτ͢ Δ ACC_SUPER The ACC_SUPER flag exists for backward compatibility with code compiled by older compilers for the Java programming language. In JDK releases prior to 1.0.2, the compiler generated access_flags in which the flag now representing ACC_SUPER had no assigned meaning, and Oracle's Java Virtual Machine implementation ignored the flag if it was set. ACC_SYNTHETIC The ACC_SYNTHETIC flag indicates that this class or interface was generated by a compiler and does not appear in source code. Table 4.1-B. Class access and property modifiers *OWPLF%ZOBNJD$PNQMJDBUFE-BNCEBKBWB

Slide 96

Slide 96 text

5JQT#4.͕࡞੒͢Δ$MBTTΛϑΝΠϧʹు͘ w ϑΝΫτϦϝιουHFU-BNCEB w ࣗ਎ͷΠϯελϯεΛ࡞੒͢Δ w 'VODUJPO*OUFSGBDFͷ BQQMZϝιουͷ࣮૷ w ϑΟʔϧυBSHͷ֨ೲ஋ͱɺϝιουࣗ ମͷҾ਺ΛΦϖϥϯυελοΫʹੵΉ w JOWPLFTUBUJDͰΦϦδφϧΫϥεͷ MBNCEBNBJO Λ࣮ߦʂ private static java.util.function.Function get$Lambda(long); descriptor: (J)Ljava/util/function/Function; flags: (0x000a) ACC_PRIVATE, ACC_STATIC Code: stack=4, locals=2, args_size=1 0: new #2 // class InvokeDynamicComplicated$$Lambda$1 3: dup 4: lload_0 5: invokespecial #19 // Method "":(J)V 8: areturn public java.lang.Object apply(java.lang.Object); descriptor: (Ljava/lang/Object;)Ljava/lang/Object; flags: (0x0001) ACC_PUBLIC Code: stack=3, locals=2, args_size=2 0: aload_0 1: getfield #15 // Field arg$1:J 4: aload_1 5: checkcast #24 // class java/lang/Integer 8: invokestatic #30 // Method InvokeDynamicComplicated.lambda$main$0:(JLjava/lang/Integer;)Ljava/lang/ Double; 11: areturn RuntimeVisibleAnnotations: 0: #22() java.lang.invoke.LambdaForm$Hidden த਎Λ೷͍ͯΈΔ

Slide 97

Slide 97 text

5JQT#4.͕࡞੒͢Δ$MBTTΛϑΝΠϧʹు͘ w ϑΝΫτϦϝιουHFU-BNCEB w ࣗ਎ͷΠϯελϯεΛ࡞੒͢Δ w 'VODUJPO*OUFSGBDFͷ BQQMZϝιουͷ࣮૷ w ϑΟʔϧυBSHͷ֨ೲ஋ͱɺϝιουࣗ ମͷҾ਺ΛΦϖϥϯυελοΫʹੵΉ w JOWPLFTUBUJDͰΦϦδφϧΫϥεͷ MBNCEBNBJO *OU %PVCMFΛ࣮ߦʂ private static java.util.function.Function get$Lambda(long); descriptor: (J)Ljava/util/function/Function; flags: (0x000a) ACC_PRIVATE, ACC_STATIC Code: stack=4, locals=2, args_size=1 0: new #2 // class InvokeDynamicComplicated$$Lambda$1 3: dup 4: lload_0 5: invokespecial #19 // Method "":(J)V 8: areturn public java.lang.Object apply(java.lang.Object); descriptor: (Ljava/lang/Object;)Ljava/lang/Object; flags: (0x0001) ACC_PUBLIC Code: stack=3, locals=2, args_size=2 0: aload_0 1: getfield #15 // Field arg$1:J 4: aload_1 5: checkcast #24 // class java/lang/Integer 8: invokestatic #30 // Method InvokeDynamicComplicated.lambda$main$0:(JLjava/lang/Integer;)Ljava/lang/ Double; 11: areturn RuntimeVisibleAnnotations: 0: #22() java.lang.invoke.LambdaForm$Hidden த਎Λ೷͍ͯΈΔ TQJO*OOFS$MBTT ͷॲཧͱಉ౳Ͱ͋Δ͜ͱ͕֬ೝͰ͖ͨ🙌

Slide 98

Slide 98 text

💡ͭ·Γʂʂ

Slide 99

Slide 99 text

-BNCEBͷੜ੒JOWPLFEZOBNJD͕ݺ͹ΕΔͱʜ public static CallSite metafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType) throws LambdaConversionException { } package invoke.dynamic; import java.util.function.Function; public class InvokeDynamicComplicated { public static void main(String[] args) { long l = 10L; Function f = (i) -> (double)i / (double)l; f.apply(1); } } @FunctionalInterface public interface Function { R apply(T t); -BNCEB.FUBGBDUPSZKBWB 0: #23 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; // MethodHandles.lookup() Ljava/lang/String; // apply Ljava/lang/invoke/MethodType; // (J)Ljava/util/function/Function; Ljava/lang/invoke/MethodType; // (Ljava/lang/Object;)Ljava/lang/Object; Ljava/lang/invoke/MethodHandle; // InvokeDynamicComplicated.lambda$main$0: (JLjava/lang/Integer;)Ljava/lang/Double; Ljava/lang/invoke/MethodType; // (Ljava/lang/Integer;)Ljava/lang/Double; )Ljava/lang/invoke/CallSite; #PPU4USBQ.FUIPE #4. Λϩʔυ͢Δ #4.͸-BNCEB.FUBGBDUPSZNFUBGBDUPSZΛJOWPLFTUBUJDͰ࣮ߦ͠ɺ$BMM4JUFΛฦ͢ w*OWPLF%ZOBNJD$PNQMFDBUFE-BNCEB/ΫϥεΛੜ੒͢Δ $BMM4JUFʹόϯυϧ͞Εͨ.FUIPE)BOEMFSΛJOWPLFWJSUVBMͰ࣮ߦ͢Δ w'VODUJPOJOUFSGBDFΛ࣮૷ͨ͠*OWPLF%ZOBNJD$PNQMFDBUFE-BNCEB/ΫϥεͷΠϯελϯεΛಘΔ $BMM4JUF͔Βฦ͖ͬͯͨΠϯελϯεͷBQQMZϝιουΛ࣮ߦ͠ɺ-BNCEBຊମΛJOWPLFTUBUJDͰ࣮ߦ͢Δʂʂʂ

Slide 100

Slide 100 text

*OWPLF%ZOBNJD ׬શ ཧղ

Slide 101

Slide 101 text

Thank You For Your Kind Attention!

Slide 102

Slide 102 text

3FGFSFODFT • Sample Code: https://github.com/ikuo-suyama/JVMDeepDive • Javaʹ͓͚Δϝιουݺग़͠ͷ࢓૊Έ • JavaͰͷinvokedynamicʹΑΔϝιουݺग़͠Λཧղ͢Δ • invokedynamicͷਆൿΛղ͘ ύʔτ̍ • invokedynamic ͷਆൿΛղ͘ ύʔτ̎ • The Java® Virtual Machine Speci fi cation • An Introduction to the Constant Pool in the JVM • Openjdk package java.lang.invoke