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 "<init>":()V 14: astore_2 15: aload_2 16: iload_1 17: invokevirtual #5 // Method method:(I)I : JOWPLFWJSUVBMΛৄ͘͠ aload_<n> Operation Load reference from local variable Forms aload_2 = 44 (0x2c) Operand Stack ... → ..., objectref Description The <n> must be an index into the local variable array of the current frame (§2.6). iload_<n> Operation Load int from local variable Forms iload_1 = 27 (0x1b) Operand Stack ... → ..., value Description The <n> must be an index into the local variable array of the current frame (§2.6). *OWPLFTKWN ൈਮ *OWPLFTDMBTT ൈਮ astore_<n> Operation Store reference into local variable Forms astore_2 = 77 (0x4d) Operand Stack ..., objectref → ... Description The <n> must be an index into the local variable array of the current frame (§2.6).
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 ൈਮ
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ྻ
(Extends cp_info) CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } 5IF$0/45"/[email protected]@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 :
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; }
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
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.
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
> 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Ͱ࣮ߦ͢Δ Β͍͠ʜ ͜Μͳγάωνϟͷϝιουͳ͍Ͱ͢ ୭Ͱ͔͢ʁʁʁ ୭Ͱ͔͢ʁʁʁ
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
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
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
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
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
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
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
= 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"/[email protected])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
= 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"/[email protected])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
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
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
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
} abstract class AbstractValidatingLambdaMetafactory { /* * For context, the comments for the following fields are marked in quotes * with their values, given this program: * interface II<T> { Object foo(T x); } * interface JJ<R extends Number> extends II<R> { } * class CC { String impl(int i) { return "impl:"+i; }} * class X { * public static void main(String[] args) { * JJ<Integer> 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
} abstract class AbstractValidatingLambdaMetafactory { /* * For context, the comments for the following fields are marked in quotes * with their values, given this program: * interface II<T> { Object foo(T x); } * interface JJ<R extends Number> extends II<R> { } * class CC { String impl(int i) { return "impl:"+i; }} * class X { * public static void main(String[] args) { * JJ<Integer> 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
= 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 ͷ࣮
= 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 ͷ࣮
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);
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ຊମϝιουΛ࣮ߦʂʂ
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."<init>":()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
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."<init>":()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
invokedynamicͷਆൿΛղ͘ ύʔτ̍ • invokedynamic ͷਆൿΛղ͘ ύʔτ̎ • The Java® Virtual Machine Speci fi cation • An Introduction to the Constant Pool in the JVM • Openjdk package java.lang.invoke