Bootstrap

openjdk17 C++源码是怎么执行字节码中<init>方法 构造方法 代码块逻辑

##有请志愿者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.class
  Last modified Oct. 30, 2024; size 973 bytes
  MD5 checksum a3f3d17f189c4662028e11e233580936
  Compiled from "OtherClass.java"
public class OtherClass
  minor version: 0
  major version: 55
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #8                          // OtherClass
  super_class: #9                         // java/lang/Object
  interfaces: 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: I
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC

  public int o;
    descriptor: I
    flags: (0x0001) ACC_PUBLIC

  public OtherClass();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: sipush        1234
         8: putfield      #2                  // Field o:I
        11: return
      LineNumberTable:
        line 1: 0
        line 4: 4

  public void dddd();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=1
         0: ldc           #3                  // String dddd
         2: astore_1
         3: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
         6: aload_1
         7: getstatic     #5                  // Field CONSTANT_O:I
        10: invokedynamic #6,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;
        15: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        18: return
      LineNumberTable:
        line 9: 0
        line 11: 3
        line 12: 18

  static {};
    descriptor: ()V
    flags: (0x0008) ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: sipush        9876
         3: putstatic     #5                  // Field CONSTANT_O:I
         6: return
      LineNumberTable:
        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\u0001


yym@yym:~/debug-java$ javap -v ByteCodeTest.class
Classfile /home/yym/debug-java/ByteCodeTest.class
  Last modified Oct. 30, 2024; size 1497 bytes
  MD5 checksum 4436ea007276698cc3c392c190653ffd
  Compiled from "ByteCodeTest.java"
public class ByteCodeTest
  minor version: 0
  major version: 55
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #3                          // ByteCodeTest
  super_class: #9                         // java/lang/Object
  interfaces: 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: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: sipush        678
         8: putfield      #2                  // Field insert:I
        11: return
      LineNumberTable:
        line 4: 0
        line 6: 4

  public static void main(java.lang.String[]) throws java.lang.Exception;
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=6, locals=4, args_size=1
         0: new           #3                  // class ByteCodeTest
         3: dup
         4: invokespecial #4                  // Method "<init>":()V
         7: astore_1
         8: ldc           #3                  // class ByteCodeTest
        10: ldc           #5                  // String testYYM
        12: iconst_2
        13: anewarray     #6                  // class java/lang/Class
        16: dup
        17: iconst_0
        18: getstatic     #7                  // Field java/lang/Integer.TYPE:Ljava/lang/Class;
        21: aastore
        22: dup
        23: iconst_1
        24: getstatic     #7                  // Field java/lang/Integer.TYPE:Ljava/lang/Class;
        27: aastore
        28: invokevirtual #8                  // Method java/lang/Class.getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
        31: astore_2
        32: aload_2
        33: aload_1
        34: iconst_2
        35: anewarray     #9                  // class java/lang/Object
        38: dup
        39: iconst_0
        40: iconst_1
        41: invokestatic  #10                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        44: aastore
        45: dup
        46: iconst_1
        47: iconst_2
        48: invokestatic  #10                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        51: aastore
        52: invokevirtual #11                 // Method java/lang/reflect/Method.invoke:(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
        55: astore_3
        56: getstatic     #12                 // Field java/lang/System.in:Ljava/io/InputStream;
        59: invokevirtual #13                 // Method java/io/InputStream.read:()I
        62: pop
        63: return
      LineNumberTable:
        line 9: 0
        line 10: 8
        line 11: 32
        line 12: 56
        line 13: 63
    Exceptions:
      throws java.lang.Exception

  public int testYYM(int, int) throws java.lang.Exception;
    descriptor: (II)I
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=3, locals=6, args_size=3
         0: new           #14                 // class OtherClass
         3: dup
         4: invokespecial #15                 // Method OtherClass."<init>":()V
         7: astore_3
         8: aload_3
         9: invokevirtual #16                 // Method OtherClass.dddd:()V
        12: aload_3
        13: invokevirtual #17                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
        16: ldc           #18                 // String CONSTANT_O
        18: invokevirtual #19                 // Method java/lang/Class.getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field;
        21: astore        4
        23: aload         4
        25: iconst_1
        26: invokevirtual #20                 // Method java/lang/reflect/Field.setAccessible:(Z)V
        29: getstatic     #21                 // Field java/lang/System.out:Ljava/io/PrintStream;
        32: aload         4
        34: aconst_null
        35: 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;)V
        41: iconst_0
        42: istore        5
        44: iload_1
        45: iload_2
        46: if_icmple     57
        49: iload_1
        50: iload_2
        51: isub
        52: istore        5
        54: goto          44
        57: iload         5
        59: iconst_1
        60: iadd
        61: aload_0
        62: getfield      #2                  // Field insert:I
        65: iadd
        66: istore        5
        68: iload         5
        70: ireturn
      LineNumberTable:
        line 16: 0
        line 17: 8
        line 18: 12
        line 19: 23
        line 20: 29
        line 21: 41
        line 22: 44
        line 23: 49
        line 25: 57
        line 26: 68
      StackMapTable: number_of_entries = 2
        frame_type = 254 /* append */
          offset_delta = 44
          locals = [ 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: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: sipush        1234
         8: putfield      #2                  // Field o:I
        11: return
      LineNumberTable:
        line 1: 0
        line 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 it
                                   Register flags    // if caller wants to test it
                                   ) {
  // determine flags
  const 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 cache
  if (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 yet
  if (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 address
    const int receiver_is_at_end      = -1;  // back off one slot to get receiver
    Address 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 shift
  ConstantPoolCacheEntry::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 pointer
  if (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 registers
  const 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 offsets
  assert(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 fields
  const 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 methods
  if (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 necessary
  Handle 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 method
  CallInfo 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 updated
  ConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry();
  if (cp_cache_entry->is_resolved(bytecode)) return;

#ifdef ASSERT
  if (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 entry
      assert(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调试

;