##有请志愿者java类和他的字节码
##java类
public class OtherClass {public static int CONSTANT_O=9876;public int o=1234;public void dddd(){String dddd = "dddd";//System.out.println(dddd);System.out.println(dddd+CONSTANT_O);}}import java.lang.reflect.Field;
import java.lang.reflect.Method;public class ByteCodeTest {private int insert=678;public static void main(String[] args) throws Exception {ByteCodeTest byteCodeTest = new ByteCodeTest();Method method = ByteCodeTest.class.getDeclaredMethod("testYYM", int.class, int.class);Object result = method.invoke(byteCodeTest, 1,2);System.in.read();}public int testYYM(int a, int b) throws Exception {OtherClass otherClass = new OtherClass();otherClass.dddd();Field field = otherClass.getClass().getDeclaredField("CONSTANT_O");field.setAccessible(true);System.out.println(field.get(null));int c = 0;while(a>b) {c = a-b;}c=c+1+this.insert;return c;}}
##字节码
yym@yym:~/debug-java$ javap -v OtherClass.class
Classfile /home/yym/debug-java/OtherClass.classLast modified Oct. 30, 2024; size 973 bytesMD5 checksum a3f3d17f189c4662028e11e233580936Compiled from "OtherClass.java"
public class OtherClassminor version: 0major version: 55flags: (0x0021) ACC_PUBLIC, ACC_SUPERthis_class: #8 // OtherClasssuper_class: #9 // java/lang/Objectinterfaces: 0, fields: 2, methods: 3, attributes: 3
Constant pool:#1 = Methodref #9.#21 // java/lang/Object."<init>":()V#2 = Fieldref #8.#22 // OtherClass.o:I#3 = String #17 // dddd#4 = Fieldref #23.#24 // java/lang/System.out:Ljava/io/PrintStream;#5 = Fieldref #8.#25 // OtherClass.CONSTANT_O:I#6 = InvokeDynamic #0:#29 // #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;#7 = Methodref #30.#31 // java/io/PrintStream.println:(Ljava/lang/String;)V#8 = Class #32 // OtherClass#9 = Class #33 // java/lang/Object#10 = Utf8 CONSTANT_O#11 = Utf8 I#12 = Utf8 o#13 = Utf8 <init>#14 = Utf8 ()V#15 = Utf8 Code#16 = Utf8 LineNumberTable#17 = Utf8 dddd#18 = Utf8 <clinit>#19 = Utf8 SourceFile#20 = Utf8 OtherClass.java#21 = NameAndType #13:#14 // "<init>":()V#22 = NameAndType #12:#11 // o:I#23 = Class #34 // java/lang/System#24 = NameAndType #35:#36 // out:Ljava/io/PrintStream;#25 = NameAndType #10:#11 // CONSTANT_O:I#26 = Utf8 BootstrapMethods#27 = MethodHandle 6:#37 // REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;#28 = String #38 // \u0001\u0001#29 = NameAndType #39:#40 // makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;#30 = Class #41 // java/io/PrintStream#31 = NameAndType #42:#43 // println:(Ljava/lang/String;)V#32 = Utf8 OtherClass#33 = Utf8 java/lang/Object#34 = Utf8 java/lang/System#35 = Utf8 out#36 = Utf8 Ljava/io/PrintStream;#37 = Methodref #44.#45 // java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;#38 = Utf8 \u0001\u0001#39 = Utf8 makeConcatWithConstants#40 = Utf8 (Ljava/lang/String;I)Ljava/lang/String;#41 = Utf8 java/io/PrintStream#42 = Utf8 println#43 = Utf8 (Ljava/lang/String;)V#44 = Class #46 // java/lang/invoke/StringConcatFactory#45 = NameAndType #39:#50 // makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;#46 = Utf8 java/lang/invoke/StringConcatFactory#47 = Class #52 // java/lang/invoke/MethodHandles$Lookup#48 = Utf8 Lookup#49 = Utf8 InnerClasses#50 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;#51 = Class #53 // java/lang/invoke/MethodHandles#52 = Utf8 java/lang/invoke/MethodHandles$Lookup#53 = Utf8 java/lang/invoke/MethodHandles
{public static int CONSTANT_O;descriptor: Iflags: (0x0009) ACC_PUBLIC, ACC_STATICpublic int o;descriptor: Iflags: (0x0001) ACC_PUBLICpublic OtherClass();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack=2, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: aload_05: sipush 12348: putfield #2 // Field o:I11: returnLineNumberTable:line 1: 0line 4: 4public void dddd();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack=3, locals=2, args_size=10: ldc #3 // String dddd2: astore_13: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;6: aload_17: getstatic #5 // Field CONSTANT_O:I10: invokedynamic #6, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;15: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V18: returnLineNumberTable:line 9: 0line 11: 3line 12: 18static {};descriptor: ()Vflags: (0x0008) ACC_STATICCode:stack=1, locals=0, args_size=00: sipush 98763: putstatic #5 // Field CONSTANT_O:I6: returnLineNumberTable:line 3: 0
}
SourceFile: "OtherClass.java"
InnerClasses:public static final #48= #47 of #51; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:0: #27 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;Method arguments:#28 \u0001\u0001yym@yym:~/debug-java$ javap -v ByteCodeTest.class
Classfile /home/yym/debug-java/ByteCodeTest.classLast modified Oct. 30, 2024; size 1497 bytesMD5 checksum 4436ea007276698cc3c392c190653ffdCompiled from "ByteCodeTest.java"
public class ByteCodeTestminor version: 0major version: 55flags: (0x0021) ACC_PUBLIC, ACC_SUPERthis_class: #3 // ByteCodeTestsuper_class: #9 // java/lang/Objectinterfaces: 0, fields: 1, methods: 3, attributes: 1
Constant pool:#1 = Methodref #9.#40 // java/lang/Object."<init>":()V#2 = Fieldref #3.#41 // ByteCodeTest.insert:I#3 = Class #42 // ByteCodeTest#4 = Methodref #3.#40 // ByteCodeTest."<init>":()V#5 = String #34 // testYYM#6 = Class #43 // java/lang/Class#7 = Fieldref #44.#45 // java/lang/Integer.TYPE:Ljava/lang/Class;#8 = Methodref #6.#46 // java/lang/Class.getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;#9 = Class #47 // java/lang/Object#10 = Methodref #44.#48 // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;#11 = Methodref #49.#50 // java/lang/reflect/Method.invoke:(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;#12 = Fieldref #51.#52 // java/lang/System.in:Ljava/io/InputStream;#13 = Methodref #53.#54 // java/io/InputStream.read:()I#14 = Class #55 // OtherClass#15 = Methodref #14.#40 // OtherClass."<init>":()V#16 = Methodref #14.#56 // OtherClass.dddd:()V#17 = Methodref #9.#57 // java/lang/Object.getClass:()Ljava/lang/Class;#18 = String #58 // CONSTANT_O#19 = Methodref #6.#59 // java/lang/Class.getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field;#20 = Methodref #37.#60 // java/lang/reflect/Field.setAccessible:(Z)V#21 = Fieldref #51.#61 // java/lang/System.out:Ljava/io/PrintStream;#22 = Methodref #37.#62 // java/lang/reflect/Field.get:(Ljava/lang/Object;)Ljava/lang/Object;#23 = Methodref #63.#64 // java/io/PrintStream.println:(Ljava/lang/Object;)V#24 = Utf8 insert#25 = Utf8 I#26 = Utf8 <init>#27 = Utf8 ()V#28 = Utf8 Code#29 = Utf8 LineNumberTable#30 = Utf8 main#31 = Utf8 ([Ljava/lang/String;)V#32 = Utf8 Exceptions#33 = Class #65 // java/lang/Exception#34 = Utf8 testYYM#35 = Utf8 (II)I#36 = Utf8 StackMapTable#37 = Class #66 // java/lang/reflect/Field#38 = Utf8 SourceFile#39 = Utf8 ByteCodeTest.java#40 = NameAndType #26:#27 // "<init>":()V#41 = NameAndType #24:#25 // insert:I#42 = Utf8 ByteCodeTest#43 = Utf8 java/lang/Class#44 = Class #67 // java/lang/Integer#45 = NameAndType #68:#69 // TYPE:Ljava/lang/Class;#46 = NameAndType #70:#71 // getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;#47 = Utf8 java/lang/Object#48 = NameAndType #72:#73 // valueOf:(I)Ljava/lang/Integer;#49 = Class #74 // java/lang/reflect/Method#50 = NameAndType #75:#76 // invoke:(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;#51 = Class #77 // java/lang/System#52 = NameAndType #78:#79 // in:Ljava/io/InputStream;#53 = Class #80 // java/io/InputStream#54 = NameAndType #81:#82 // read:()I#55 = Utf8 OtherClass#56 = NameAndType #83:#27 // dddd:()V#57 = NameAndType #84:#85 // getClass:()Ljava/lang/Class;#58 = Utf8 CONSTANT_O#59 = NameAndType #86:#87 // getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field;#60 = NameAndType #88:#89 // setAccessible:(Z)V#61 = NameAndType #90:#91 // out:Ljava/io/PrintStream;#62 = NameAndType #92:#93 // get:(Ljava/lang/Object;)Ljava/lang/Object;#63 = Class #94 // java/io/PrintStream#64 = NameAndType #95:#96 // println:(Ljava/lang/Object;)V#65 = Utf8 java/lang/Exception#66 = Utf8 java/lang/reflect/Field#67 = Utf8 java/lang/Integer#68 = Utf8 TYPE#69 = Utf8 Ljava/lang/Class;#70 = Utf8 getDeclaredMethod#71 = Utf8 (Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;#72 = Utf8 valueOf#73 = Utf8 (I)Ljava/lang/Integer;#74 = Utf8 java/lang/reflect/Method#75 = Utf8 invoke#76 = Utf8 (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;#77 = Utf8 java/lang/System#78 = Utf8 in#79 = Utf8 Ljava/io/InputStream;#80 = Utf8 java/io/InputStream#81 = Utf8 read#82 = Utf8 ()I#83 = Utf8 dddd#84 = Utf8 getClass#85 = Utf8 ()Ljava/lang/Class;#86 = Utf8 getDeclaredField#87 = Utf8 (Ljava/lang/String;)Ljava/lang/reflect/Field;#88 = Utf8 setAccessible#89 = Utf8 (Z)V#90 = Utf8 out#91 = Utf8 Ljava/io/PrintStream;#92 = Utf8 get#93 = Utf8 (Ljava/lang/Object;)Ljava/lang/Object;#94 = Utf8 java/io/PrintStream#95 = Utf8 println#96 = Utf8 (Ljava/lang/Object;)V
{public ByteCodeTest();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack=2, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: aload_05: sipush 6788: putfield #2 // Field insert:I11: returnLineNumberTable:line 4: 0line 6: 4public static void main(java.lang.String[]) throws java.lang.Exception;descriptor: ([Ljava/lang/String;)Vflags: (0x0009) ACC_PUBLIC, ACC_STATICCode:stack=6, locals=4, args_size=10: new #3 // class ByteCodeTest3: dup4: invokespecial #4 // Method "<init>":()V7: astore_18: ldc #3 // class ByteCodeTest10: ldc #5 // String testYYM12: iconst_213: anewarray #6 // class java/lang/Class16: dup17: iconst_018: getstatic #7 // Field java/lang/Integer.TYPE:Ljava/lang/Class;21: aastore22: dup23: iconst_124: getstatic #7 // Field java/lang/Integer.TYPE:Ljava/lang/Class;27: aastore28: invokevirtual #8 // Method java/lang/Class.getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;31: astore_232: aload_233: aload_134: iconst_235: anewarray #9 // class java/lang/Object38: dup39: iconst_040: iconst_141: invokestatic #10 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;44: aastore45: dup46: iconst_147: iconst_248: invokestatic #10 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;51: aastore52: invokevirtual #11 // Method java/lang/reflect/Method.invoke:(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;55: astore_356: getstatic #12 // Field java/lang/System.in:Ljava/io/InputStream;59: invokevirtual #13 // Method java/io/InputStream.read:()I62: pop63: returnLineNumberTable:line 9: 0line 10: 8line 11: 32line 12: 56line 13: 63Exceptions:throws java.lang.Exceptionpublic int testYYM(int, int) throws java.lang.Exception;descriptor: (II)Iflags: (0x0001) ACC_PUBLICCode:stack=3, locals=6, args_size=30: new #14 // class OtherClass3: dup4: invokespecial #15 // Method OtherClass."<init>":()V7: astore_38: aload_39: invokevirtual #16 // Method OtherClass.dddd:()V12: aload_313: invokevirtual #17 // Method java/lang/Object.getClass:()Ljava/lang/Class;16: ldc #18 // String CONSTANT_O18: invokevirtual #19 // Method java/lang/Class.getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field;21: astore 423: aload 425: iconst_126: invokevirtual #20 // Method java/lang/reflect/Field.setAccessible:(Z)V29: getstatic #21 // Field java/lang/System.out:Ljava/io/PrintStream;32: aload 434: aconst_null35: invokevirtual #22 // Method java/lang/reflect/Field.get:(Ljava/lang/Object;)Ljava/lang/Object;38: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V41: iconst_042: istore 544: iload_145: iload_246: if_icmple 5749: iload_150: iload_251: isub52: istore 554: goto 4457: iload 559: iconst_160: iadd61: aload_062: getfield #2 // Field insert:I65: iadd66: istore 568: iload 570: ireturnLineNumberTable:line 16: 0line 17: 8line 18: 12line 19: 23line 20: 29line 21: 41line 22: 44line 23: 49line 25: 57line 26: 68StackMapTable: number_of_entries = 2frame_type = 254 /* append */offset_delta = 44locals = [ class OtherClass, class java/lang/reflect/Field, int ]frame_type = 12 /* same */Exceptions:throws java.lang.Exception
}
SourceFile: "ByteCodeTest.java"
##init方法字节码,那openjdk17 hotspot是怎么执行这个方法的呢?
查看testYYM方法字节码,new OtherClass对象,invokespecial调用init方法
0: new #14 // class OtherClass
4: invokespecial #15 // Method OtherClass."<init>":()V
public OtherClass();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack=2, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: aload_05: sipush 12348: putfield #2 // Field o:I11: returnLineNumberTable:line 1: 0line 4: 4
##openjdk17 hotspot 调用init方法源码步骤
模版解释器解释指令Bytecodes::_invokespecial
InterpreterRuntime::resolve_invoke 找到// Method OtherClass."<init>":()V
##templateTable_x86.cpp文件void TemplateTable::prepare_invoke(int byte_no,Register method, // linked method (or i-klass)Register index, // itable index, MethodType, etc.Register recv, // if caller wants to see itRegister flags // if caller wants to test it) {// determine flagsconst Bytecodes::Code code = bytecode();const bool is_invokeinterface = code == Bytecodes::_invokeinterface;const bool is_invokedynamic = code == Bytecodes::_invokedynamic;const bool is_invokehandle = code == Bytecodes::_invokehandle;const bool is_invokevirtual = code == Bytecodes::_invokevirtual;const bool is_invokespecial = code == Bytecodes::_invokespecial;const bool load_receiver = (recv != noreg);const bool save_flags = (flags != noreg);assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), "");assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal");assert(flags == noreg || flags == rdx, "");assert(recv == noreg || recv == rcx, "");// setup registers & access constant pool cacheif (recv == noreg) recv = rcx;if (flags == noreg) flags = rdx;assert_different_registers(method, index, recv, flags);// save 'interpreter return address'__ save_bcp();load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);// maybe push appendix to arguments (just before return address)if (is_invokedynamic || is_invokehandle) {Label L_no_push;__ testl(flags, (1 << ConstantPoolCacheEntry::has_appendix_shift));__ jcc(Assembler::zero, L_no_push);// Push the appendix as a trailing parameter.// This must be done before we get the receiver,// since the parameter_size includes it.__ push(rbx);__ mov(rbx, index);__ load_resolved_reference_at_index(index, rbx);__ pop(rbx);__ push(index); // push appendix (MethodType, CallSite, etc.)__ bind(L_no_push);}// load receiver if needed (after appendix is pushed so parameter size is correct)// Note: no return address pushed yetif (load_receiver) {__ movl(recv, flags);__ andl(recv, ConstantPoolCacheEntry::parameter_size_mask);const int no_return_pc_pushed_yet = -1; // argument slot correction before we push return addressconst int receiver_is_at_end = -1; // back off one slot to get receiverAddress recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end);__ movptr(recv, recv_addr);__ verify_oop(recv);}if (save_flags) {__ movl(rbcp, flags);}// compute return type__ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);// Make sure we don't need to mask flags after the above shiftConstantPoolCacheEntry::verify_tos_state_shift();// load return address{const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);ExternalAddress table(table_addr);LP64_ONLY(__ lea(rscratch1, table));LP64_ONLY(__ movptr(flags, Address(rscratch1, flags, Address::times_ptr)));NOT_LP64(__ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr))));}// push return address__ push(flags);// Restore flags value from the constant pool cache, and restore rsi// for later null checks. r13 is the bytecode pointerif (save_flags) {__ movl(flags, rbcp);__ restore_bcp();}
}void TemplateTable::load_invoke_cp_cache_entry(int byte_no,Register method,Register itable_index,Register flags,bool is_invokevirtual,bool is_invokevfinal, /*unused*/bool is_invokedynamic) {// setup registersconst Register cache = rcx;const Register index = rdx;assert_different_registers(method, flags);assert_different_registers(method, cache, index);assert_different_registers(itable_index, flags);assert_different_registers(itable_index, cache, index);// determine constant pool cache field offsetsassert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant");const int flags_offset = in_bytes(ConstantPoolCache::base_offset() +ConstantPoolCacheEntry::flags_offset());// access constant pool cache fieldsconst int index_offset = in_bytes(ConstantPoolCache::base_offset() +ConstantPoolCacheEntry::f2_offset());size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));resolve_cache_and_index(byte_no, cache, index, index_size);__ load_resolved_method_at_index(byte_no, method, cache, index);if (itable_index != noreg) {// pick up itable or appendix index from f2 also:__ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset));}__ movl(flags, Address(cache, index, Address::times_ptr, flags_offset));
}void TemplateTable::resolve_cache_and_index(int byte_no,Register cache,Register index,size_t index_size) {const Register temp = rbx;assert_different_registers(cache, index, temp);Label L_clinit_barrier_slow;Label resolved;Bytecodes::Code code = bytecode();switch (code) {case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;default: break;}assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");__ get_cache_and_index_and_bytecode_at_bcp(cache, index, temp, byte_no, 1, index_size);__ cmpl(temp, code); // have we resolved this bytecode?__ jcc(Assembler::equal, resolved);// resolve first time through// Class initialization barrier slow path lands here as well.__ bind(L_clinit_barrier_slow);// std::cout << "@@@@yym%%%%" << "method begin" << "----begin" << std::endl;address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);__ movl(temp, code);__ call_VM(noreg, entry, temp);// std::cout << "@@@@yym%%%%" << "method end" << "----end" << std::endl;// Update registers with resolved info__ get_cache_and_index_at_bcp(cache, index, 1, index_size);__ bind(resolved);// Class initialization barrier for static methodsif (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {const Register method = temp;const Register klass = temp;const Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg);assert(thread != noreg, "x86_32 not supported");__ load_resolved_method_at_index(byte_no, method, cache, index);__ load_method_holder(klass, method);__ clinit_barrier(klass, thread, NULL /*L_fast_path*/, &L_clinit_barrier_slow);}
}##interpreterRuntime.cpp文件
##找到OtherClass.<init>()V方法
void InterpreterRuntime::resolve_invoke(JavaThread* current, Bytecodes::Code bytecode) {LastFrameAccessor last_frame(current);// extract receiver from the outgoing argument list if necessaryHandle receiver(current, NULL);if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface ||bytecode == Bytecodes::_invokespecial) {ResourceMark rm(current);methodHandle m (current, last_frame.method());Bytecode_invoke call(m, last_frame.bci());Symbol* signature = call.signature();receiver = Handle(current, last_frame.callee_receiver(signature));assert(Universe::heap()->is_in_or_null(receiver()),"sanity check");assert(receiver.is_null() ||!Universe::heap()->is_in(receiver->klass()),"sanity check");}// resolve methodCallInfo info;constantPoolHandle pool(current, last_frame.method()->constants());methodHandle resolved_method;{JvmtiHideSingleStepping jhss(current);JavaThread* THREAD = current; // For exception macros.LinkResolver::resolve_invoke(info, receiver, pool,last_frame.get_index_u2_cpcache(bytecode), bytecode,CHECK);if (JvmtiExport::can_hotswap_or_post_breakpoint() && info.resolved_method()->is_old()) {resolved_method = methodHandle(current, info.resolved_method()->get_new_method());} else {resolved_method = methodHandle(current, info.resolved_method());}} // end JvmtiHideSingleStepping// check if link resolution caused cpCache to be updatedConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry();if (cp_cache_entry->is_resolved(bytecode)) return;#ifdef ASSERTif (bytecode == Bytecodes::_invokeinterface) {if (resolved_method->method_holder() == vmClasses::Object_klass()) {// NOTE: THIS IS A FIX FOR A CORNER CASE in the JVM spec// (see also CallInfo::set_interface for details)assert(info.call_kind() == CallInfo::vtable_call ||info.call_kind() == CallInfo::direct_call, "");assert(resolved_method->is_final() || info.has_vtable_index(),"should have been set already");} else if (!resolved_method->has_itable_index()) {// Resolved something like CharSequence.toString. Use vtable not itable.assert(info.call_kind() != CallInfo::itable_call, "");} else {// Setup itable entryassert(info.call_kind() == CallInfo::itable_call, "");int index = resolved_method->itable_index();assert(info.itable_index() == index, "");}} else if (bytecode == Bytecodes::_invokespecial) {assert(info.call_kind() == CallInfo::direct_call, "must be direct call");} else {assert(info.call_kind() == CallInfo::direct_call ||info.call_kind() == CallInfo::vtable_call, "");}
#endif// Get sender and only set cpCache entry to resolved if it is not an// interface. The receiver for invokespecial calls within interface// methods must be checked for every call.InstanceKlass* sender = pool->pool_holder();switch (info.call_kind()) {case CallInfo::direct_call:cp_cache_entry->set_direct_call(bytecode,resolved_method,sender->is_interface());break;case CallInfo::vtable_call:cp_cache_entry->set_vtable_call(bytecode,resolved_method,info.vtable_index());break;case CallInfo::itable_call:cp_cache_entry->set_itable_call(bytecode,info.resolved_klass(),resolved_method,info.itable_index());break;default: ShouldNotReachHere();}
}
##GDB调试