zoukankan      html  css  js  c++  java
  • jvm源码解读--12 invokspecial指令的解读

    先看代码

    package com.zyt.jvmbook;
    
    public class Girl extends Person{
        public Girl() {
            int a;
        }
    
        @Override
        public void sayHello() {
            System.out.println("girl say hello");
        }
        private void sayHi(){
            System.out.println("hellow");
        }
    
        public static void main(String[] args) {
            Person p = new Girl();
    
            p.sayHello();
            Girl g=new Girl();
            g.sayHello();
            g.sayHi();
    
        }
    }

    查看编译后的内容

     0 new #6 <com/zyt/jvmbook/Girl>
     3 dup
     4 invokespecial #7 <com/zyt/jvmbook/Girl.<init>>
     7 astore_1
     8 aload_1
     9 invokevirtual #8 <com/zyt/jvmbook/Person.sayHello>
    12 new #6 <com/zyt/jvmbook/Girl>
    15 dup
    16 invokespecial #7 <com/zyt/jvmbook/Girl.<init>>
    19 astore_2
    20 aload_2
    21 invokevirtual #9 <com/zyt/jvmbook/Girl.sayHello>
    24 aload_2
    25 invokespecial #10 <com/zyt/jvmbook/Girl.sayHi>
    28 return

    看这个,对invoke孙ecial #7的解读

    这个可真是费劲死了 弄了我两天,现在才搞清楚

    之前的dup指令分析了是复制oop对象,那么此时操作数栈中是什么呢

    ///////高地址

    oop

    oop

    //低地址

    那么贴出invokespecail指令

    ----------------------------------------------------------------------
    invokespecial  183 invokespecial  [0x0000000002cf1da0, 0x0000000002cf2040]  672 bytes
    
    0x0000000002cf1da0: push   %rax
    0x0000000002cf1da1: jmpq   0x0000000002cf1dd0
    0x0000000002cf1da6: sub    $0x8,%rsp
    0x0000000002cf1daa: vmovss %xmm0,(%rsp)
    0x0000000002cf1daf: jmpq   0x0000000002cf1dd0
    0x0000000002cf1db4: sub    $0x10,%rsp
    0x0000000002cf1db8: vmovsd %xmm0,(%rsp)
    0x0000000002cf1dbd: jmpq   0x0000000002cf1dd0
    0x0000000002cf1dc2: sub    $0x10,%rsp
    0x0000000002cf1dc6: mov    %rax,(%rsp)
    0x0000000002cf1dca: jmpq   0x0000000002cf1dd0
    
    
    0x0000000002cf1dcf: push   %rax
            开始执行.有栈顶缓存,即rax中有值
    //    void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
    //                                                           int bcp_offset,
    //                                                           size_t index_size) {
    //        assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
    //        if (index_size == sizeof(u2)) {
    //            load_unsigned_short(index, Address(r13, bcp_offset));}
    0x0000000002cf1dd0: mov    %r13,-0x38(%rbp) //bcp的地址
    0x0000000002cf1dd4: movzwl 0x1(%r13),%edx
    0x0000000002cf1dd9: mov    -0x28(%rbp),%rcx  将cache放到rcx
    0x0000000002cf1ddd: shl    $0x2,%edx
    //movl(bytecode, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()));
    //那么cache就是rcx,index就是rdx
    0x0000000002cf1de0: mov    0x10(%rcx,%rdx,8),%ebx 取得cache的_indices的, 0x10 + rcx + rdx*8
    //  const int shift_count = (1 + byte_no) * BitsPerByte;
    
    //  shrl(bytecode, shift_count);
    0x0000000002cf1de4: shr    $0x10,%ebx
    0x0000000002cf1de7: and    $0xff,%ebx
    0x0000000002cf1ded: cmp    $0xb7,%ebx
    0x0000000002cf1df3: je     0x0000000002cf1e9a
    //验证时否为0xb7
    //在invokevirtual、invokespecial等字节码指令对应的汇编片段中,如果_indices中的b2或b1不为字节码指令的操作码,
    // 说明方法还没有连接,需要调用InterpreterRuntime::resolve_invoke()方法生成ConstantPoolCacheEntry。
    ---解析ConstantPoolCacheEntry---开始
    0x0000000002cf1df9: mov    $0xb7,%ebx
    0x0000000002cf1dfe: callq  0x0000000002cf1e08
    
    0x0000000002cf1e03: jmpq   0x0000000002cf1e8e
    0x0000000002cf1e08: mov    %rbx,%rdx
    0x0000000002cf1e0b: lea    0x8(%rsp),%rax
    0x0000000002cf1e10: mov    %r13,-0x38(%rbp)
    0x0000000002cf1e14: mov    %r15,%rcx
    0x0000000002cf1e17: mov    %rbp,0x1e8(%r15)
    0x0000000002cf1e1e: mov    %rax,0x1d8(%r15)
    0x0000000002cf1e25: sub    $0x20,%rsp
    0x0000000002cf1e29: test   $0xf,%esp
    0x0000000002cf1e2f: je     0x0000000002cf1e47
    0x0000000002cf1e35: sub    $0x8,%rsp
    0x0000000002cf1e39: callq  0x000000005449a3c0
    0x0000000002cf1e3e: add    $0x8,%rsp
    0x0000000002cf1e42: jmpq   0x0000000002cf1e4c
    0x0000000002cf1e47: callq  0x000000005449a3c0
    0x0000000002cf1e4c: add    $0x20,%rsp
    0x0000000002cf1e50: movabs $0x0,%r10
    0x0000000002cf1e5a: mov    %r10,0x1d8(%r15)
    0x0000000002cf1e61: movabs $0x0,%r10
    0x0000000002cf1e6b: mov    %r10,0x1e8(%r15)
    0x0000000002cf1e72: cmpq   $0x0,0x8(%r15)
    0x0000000002cf1e7a: je     0x0000000002cf1e85
    0x0000000002cf1e80: jmpq   0x0000000002cd07e0
    0x0000000002cf1e85: mov    -0x38(%rbp),%r13
    0x0000000002cf1e89: mov    -0x30(%rbp),%r14
    0x0000000002cf1e8d: retq
    0x0000000002cf1e8e: movzwl 0x1(%r13),%edx
    0x0000000002cf1e93: mov    -0x28(%rbp),%rcx
    0x0000000002cf1e97: shl    $0x2,%edx
    
    ---解析ConstantPoolCacheEntry---完成
    //__ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
    //method_offset=24,取得method
    0x0000000002cf1e9a: mov    0x18(%rcx,%rdx,8),%rbx
    //  __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset));
    //取得flag
    //取得flag
    0x0000000002cf1e9f: mov    0x28(%rcx,%rdx,8),%edx
    //  if (load_receiver) {
    //    __ movl(recv, flags);
    0x0000000002cf1ea3: mov    %edx,%ecx
    //    __ andl(recv, ConstantPoolCacheEntry::parameter_size_mask);
    0x0000000002cf1ea5: and    $0xff,%ecx
    //    __ movptr(recv, recv_addr);
    0x0000000002cf1eab: mov    -0x8(%rsp,%rcx,8),%rcx //-0x8 + rsp+ 8*rcx  to rcx;
    //  // compute return type
    //获取tosState
    (gdb) p/x _invoke_return_entry
     $1 = {0x7f1a6d006e80, 0x7f1a6d006f50, 0x7f1a6d007020,
           0x7f1a6d0070f0, 0x7f1a6d0071c0, 0x7f1a6d007290,
           0x7f1a6d007360, 0x7f1a6d007430, 0x7f1a6d007500}
    0x0000000002cf1eb0: shr    $0x1c,%edx
    0x0000000002cf1eb3: movabs $0x54bcbba0,%r10  //_invoke_return_entry
    0x0000000002cf1ebd: mov    (%r10,%rdx,8),%rdx  获取返回entry
    //  __ push(flags);// push return address
    0x0000000002cf1ec1: push   %rdx
    0x0000000002cf1ec2: cmp    (%rcx),%rax //cache,
    //    movptr(mdp, Address(rbp, frame::interpreter_frame_mdx_offset * wordSize));
    //    testptr(mdp, mdp);
    //  jcc(Assembler::zero, zero_continue);
    0x0000000002cf1ec5: mov    -0x20(%rbp),%rax   //methodData
    0x0000000002cf1ec9: test   %rax,%rax
    0x0000000002cf1ecc: je     0x0000000002cf1ee4
    //    increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
    //
    //    // The method data pointer needs to be updated to reflect the new target.
    //    update_mdp_by_constant(mdp, in_bytes(CounterData::counter_data_size()));
    //    bind(profile_continue);
    0x0000000002cf1ed2: addq   $0x1,0x8(%rax)
    0x0000000002cf1ed7: sbbq   $0x0,0x8(%rax)
    0x0000000002cf1edc: add    $0x10,%rax
    0x0000000002cf1ee0: mov    %rax,-0x20(%rbp)
    
    
    0x0000000002cf1ee4: mov    -0x20(%rbp),%rax
    0x0000000002cf1ee8: test   %rax,%rax
    0x0000000002cf1eeb: je     0x0000000002cf2020
    
    0x0000000002cf1ef1: cmpb   $0xa,-0x10(%rax)
    0x0000000002cf1ef5: jne    0x0000000002cf2020
    0x0000000002cf1efb: add    $0x8,%rax
    0x0000000002cf1eff: mov    -0x8(%rax),%r13
    0x0000000002cf1f03: sub    $0x0,%r13d
    0x0000000002cf1f07: cmp    $0x2,%r13d
    0x0000000002cf1f0b: jl     0x0000000002cf2015
    0x0000000002cf1f11: mov    0x8(%rbx),%r13
    0x0000000002cf1f15: movzwl 0x2a(%r13),%r13d
    0x0000000002cf1f1a: sub    (%rax),%r13
    0x0000000002cf1f1d: sub    $0x1,%r13d
    0x0000000002cf1f21: mov    0x8(%rsp,%r13,8),%r13
    0x0000000002cf1f26: test   %r13,%r13
    0x0000000002cf1f29: jne    0x0000000002cf1f35
    0x0000000002cf1f2b: orq    $0x1,0x8(%rax)
    0x0000000002cf1f33: jmp    0x0000000002cf1f82
    0x0000000002cf1f35: mov    0x8(%r13),%r13d
    0x0000000002cf1f39: shl    $0x3,%r13
    0x0000000002cf1f3d: xor    0x8(%rax),%r13
    0x0000000002cf1f41: test   $0xfffffffffffffffc,%r13
    0x0000000002cf1f48: je     0x0000000002cf1f82
    0x0000000002cf1f4a: test   $0x2,%r13
    0x0000000002cf1f51: jne    0x0000000002cf1f82
    0x0000000002cf1f53: cmpq   $0x0,0x8(%rax)
    0x0000000002cf1f5b: je     0x0000000002cf1f7e
    0x0000000002cf1f5d: cmpq   $0x1,0x8(%rax)
    0x0000000002cf1f65: je     0x0000000002cf1f7e
    0x0000000002cf1f67: xor    0x8(%rax),%r13
    0x0000000002cf1f6b: test   $0xfffffffffffffffc,%r13
    0x0000000002cf1f72: je     0x0000000002cf1f82
    0x0000000002cf1f74: orq    $0x2,0x8(%rax)
    0x0000000002cf1f7c: jmp    0x0000000002cf1f82
    0x0000000002cf1f7e: mov    %r13,0x8(%rax)
    0x0000000002cf1f82: add    $0x10,%rax
    0x0000000002cf1f86: mov    -0x18(%rax),%r13
    0x0000000002cf1f8a: sub    $0x2,%r13d
    0x0000000002cf1f8e: cmp    $0x2,%r13d
    0x0000000002cf1f92: jl     0x0000000002cf2015
    0x0000000002cf1f98: mov    0x8(%rbx),%r13
    0x0000000002cf1f9c: movzwl 0x2a(%r13),%r13d
    0x0000000002cf1fa1: sub    (%rax),%r13
    0x0000000002cf1fa4: sub    $0x1,%r13d
    0x0000000002cf1fa8: mov    0x8(%rsp,%r13,8),%r13
    0x0000000002cf1fad: test   %r13,%r13
    0x0000000002cf1fb0: jne    0x0000000002cf1fbc
    0x0000000002cf1fb2: orq    $0x1,0x8(%rax)
    0x0000000002cf1fba: jmp    0x0000000002cf2009
    0x0000000002cf1fbc: mov    0x8(%r13),%r13d
    0x0000000002cf1fc0: shl    $0x3,%r13
    0x0000000002cf1fc4: xor    0x8(%rax),%r13
    0x0000000002cf1fc8: test   $0xfffffffffffffffc,%r13
    0x0000000002cf1fcf: je     0x0000000002cf2009
    0x0000000002cf1fd1: test   $0x2,%r13
    0x0000000002cf1fd8: jne    0x0000000002cf2009
    0x0000000002cf1fda: cmpq   $0x0,0x8(%rax)
    0x0000000002cf1fe2: je     0x0000000002cf2005
    0x0000000002cf1fe4: cmpq   $0x1,0x8(%rax)
    0x0000000002cf1fec: je     0x0000000002cf2005
    0x0000000002cf1fee: xor    0x8(%rax),%r13
    0x0000000002cf1ff2: test   $0xfffffffffffffffc,%r13
    0x0000000002cf1ff9: je     0x0000000002cf2009
    0x0000000002cf1ffb: orq    $0x2,0x8(%rax)
    0x0000000002cf2003: jmp    0x0000000002cf2009
    0x0000000002cf2005: mov    %r13,0x8(%rax)
    0x0000000002cf2009: add    $0x10,%rax
    0x0000000002cf200d: mov    -0x28(%rax),%r13
    0x0000000002cf2011: sub    $0x4,%r13d
    0x0000000002cf2015: shl    $0x3,%r13d
    0x0000000002cf2019: add    %r13,%rax
    0x0000000002cf201c: mov    %rax,-0x20(%rbp)
    
        void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
            // set sender sp
            lea(r13, Address(rsp, wordSize));
            // record last_sp
            movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13);
        }
    
    0x0000000002cf2020: lea    0x8(%rsp),%r13
    0x0000000002cf2025: mov    %r13,-0x10(%rbp)
    
        jmp(Address(method, Method::from_interpreted_offset()));
      //jump到这里  volatile address           _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry
    
    0x0000000002cf2029: jmpq   *0x50(%rbx)
    0x0000000002cf202c: nopl   0x0(%rax)
    0x0000000002cf2030: add    %al,(%rax)
    0x0000000002cf2032: add    %al,(%rax)
    0x0000000002cf2034: add    %al,(%rax)
    0x0000000002cf2036: add    %al,(%rax)
    0x0000000002cf2038: add    %al,(%rax)
    0x0000000002cf203a: add    %al,(%rax)
    0x0000000002cf203c: add    %al,(%rax)
    0x0000000002cf203e: add    %al,(%rax)
    
    ----------------------------------------------------------------------

    对应的代码为

    void TemplateTable::invokespecial(int byte_no) {
        transition(vtos, vtos);
        assert(byte_no == f1_byte, "use this argument");
        prepare_invoke(byte_no, rbx, noreg,  // get f1 Method*
                       rcx);  // get receiver also for null check
        __ verify_oop(rcx);
        __ null_check(rcx);
        // do the call
        __ profile_call(rax);
        __ profile_arguments_type(rax, rbx, r13, false);
        __ jump_from_interpreted(rbx, rax);
    }
    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);//true
        const bool save_flags          = (flags != noreg);//false
        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
        //recv=rcx,flags=noreg
        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);
            assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
            __ 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) {//true
            __ 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) {//false
            __ movl(r13, 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);
            __ lea(rscratch1, table);
            __ movptr(flags, Address(rscratch1, 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, r13);
            __ restore_bcp();
        }
    }
    //
    void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
                                                           int bcp_offset,
                                                           size_t index_size) {
        assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
        if (index_size == sizeof(u2)) {
            load_unsigned_short(index, Address(r13, bcp_offset));}
    //返回
        void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
                                                                   Register index,
                                                                   int bcp_offset,
                                                                   size_t index_size) {
            assert_different_registers(cache, index);
            get_cache_index_at_bcp(index, bcp_offset, index_size); //将index返回值,即为index是bcp的地址的invoke指令的操作数
            movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));//将cache放入cache这个变量
            assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
            // convert from field index to ConstantPoolCacheEntry index
            assert(exact_log2(in_words(ConstantPoolCacheEntry::size())) == 2, "else change next line");
            shll(index, 2);
        }
        void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache,
                                                                                Register index,
                                                                                Register bytecode,
                                                                                int byte_no,
                                                                                int bcp_offset,
                                                                                size_t index_size) {
            get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size);//上边的执行到这里
            // We use a 32-bit load here since the layout of 64-bit words on
            // little-endian machines allow us that.
            //cache  就是constanpoolcache,那么这个操作就是取得方法重写过后的方法所在常量池的序号index
            movl(bytecode, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()));
            const int shift_count = (1 + byte_no) * BitsPerByte;
            assert((byte_no == TemplateTable::f1_byte && shift_count == ConstantPoolCacheEntry::bytecode_1_shift) ||
                   (byte_no == TemplateTable::f2_byte && shift_count == ConstantPoolCacheEntry::bytecode_2_shift),
                   "correct shift count");
            shrl(bytecode, shift_count);//右移16为
            assert(ConstantPoolCacheEntry::bytecode_1_mask == ConstantPoolCacheEntry::bytecode_2_mask, "common mask");
            andl(bytecode, ConstantPoolCacheEntry::bytecode_1_mask);
        }
    -------

    看主要的逻辑,只有一个push,这个具体的和hsdb对不上,就先不追细节了

    //  __ push(flags);// push return address
    0x0000000002cf1ec1: push   %rdx

    接着节点是

        jmp(Address(method, Method::from_interpreted_offset()));
      //jump到这里  volatile address           _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry
    
    0x0000000002cf2029: jmpq   *0x50(%rbx)

    就是跳转到了method方法的_from_interpreted_entry

    这个怎么来的呢?这个是在方法链接从时候设置的

    void InstanceKlass::link_methods(TRAPS) {
      int len = methods()->length();
      for (int i = len-1; i >= 0; i--) {
        methodHandle m(THREAD, methods()->at(i));
    
        // Set up method entry points for compiler and interpreter    .
        m->link_method(m, CHECK);
    
        // This is for JVMTI and unrelated to relocator but the last thing we do
    #ifdef ASSERT
        if (StressMethodComparator) {
          ResourceMark rm(THREAD);
          static int nmc = 0;
          for (int j = i; j >= 0 && j >= i-4; j--) {
            if ((++nmc % 1000) == 0)  tty->print_cr("Have run MethodComparator %d times...", nmc);
            bool z = MethodComparator::methods_EMCP(m(),
                       methods()->at(j));
            if (j == i && !z) {
              tty->print("MethodComparator FAIL: "); m->print(); m->print_codes();
              assert(z, "method must compare equal to itself");
            }
          }
        }
    #endif //ASSERT
      }
    }

    还有

    // Called when the method_holder is getting linked. Setup entrypoints so the method
    // is ready to be called from interpreter, compiler, and vtables.
    void Method::link_method(methodHandle h_method, TRAPS) {
      // If the code cache is full, we may reenter this function for the
      // leftover methods that weren't linked.
      if (_i2i_entry != NULL) return;
    
      assert(_adapter == NULL, "init'd to NULL" );
      assert( _code == NULL, "nothing compiled yet" );
    
      // Setup interpreter entrypoint
      assert(this == h_method(), "wrong h_method()" );
      address entry = Interpreter::entry_for_method(h_method);
      assert(entry != NULL, "interpreter entry must be non-null");
      // Sets both _i2i_entry and _from_interpreted_entry
      set_interpreter_entry(entry);
    
      // Don't overwrite already registered native entries.
      if (is_native() && !has_native_function()) {
        set_native_function(
          SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
          !native_bind_event_is_interesting);
      }
    
      // Setup compiler entrypoint.  This is made eagerly, so we do not need
      // special handling of vtables.  An alternative is to make adapters more
      // lazily by calling make_adapter() from from_compiled_entry() for the
      // normal calls.  For vtable calls life gets more complicated.  When a
      // call-site goes mega-morphic we need adapters in all methods which can be
      // called from the vtable.  We need adapters on such methods that get loaded
      // later.  Ditto for mega-morphic itable calls.  If this proves to be a
      // problem we'll make these lazily later.
      (void) make_adapters(h_method, CHECK);
    
      // ONLY USE the h_method now as make_adapter may have blocked
    
    }

    //以上是设置

      static address    entry_for_kind(MethodKind k)
      { assert(0 <= k && k < number_of_method_entries, "illegal kind"); return _entry_table[k]; }
      static address    entry_for_method(methodHandle m)            { return entry_for_kind(method_kind(m)); }

    设置

      void set_interpreter_entry(address entry)      { _i2i_entry = entry;  _from_interpreted_entry = entry; }

    设置之前的method内容

    方法的执行过程
    enum MethodKind {
        zerolocals,                                                 // method needs locals initialization
        zerolocals_synchronized,                                    // method needs locals initialization & is synchronized
        native,                                                     // native method
        native_synchronized,                                        // native method & is synchronized
        empty,                                                      // empty method (code: _return)
        accessor,                                                   // accessor method (code: _aload_0, _getfield, _(a|i)return)
        abstract,                                                   // abstract method (throws an AbstractMethodException)
        method_handle_invoke_FIRST,                                 // java.lang.invoke.MethodHandles::invokeExact, etc.
        method_handle_invoke_LAST                                   = (method_handle_invoke_FIRST
                                                                       + (vmIntrinsics::LAST_MH_SIG_POLY
                                                                          - vmIntrinsics::FIRST_MH_SIG_POLY)),
        java_lang_math_sin,                                         // implementation of java.lang.Math.sin   (x)
        java_lang_math_cos,                                         // implementation of java.lang.Math.cos   (x)
        java_lang_math_tan,                                         // implementation of java.lang.Math.tan   (x)
        java_lang_math_abs,                                         // implementation of java.lang.Math.abs   (x)
        java_lang_math_sqrt,                                        // implementation of java.lang.Math.sqrt  (x)
        java_lang_math_log,                                         // implementation of java.lang.Math.log   (x)
        java_lang_math_log10,                                       // implementation of java.lang.Math.log10 (x)
        java_lang_math_pow,                                         // implementation of java.lang.Math.pow   (x,y)
        java_lang_math_exp,                                         // implementation of java.lang.Math.exp   (x)
        java_lang_ref_reference_get,                                // implementation of java.lang.ref.Reference.get()
        java_util_zip_CRC32_update,                                 // implementation of java.util.zip.CRC32.update()
        java_util_zip_CRC32_updateBytes,                            // implementation of java.util.zip.CRC32.updateBytes()
        java_util_zip_CRC32_updateByteBuffer,                       // implementation of java.util.zip.CRC32.updateByteBuffer()
        number_of_method_entries, //26
        invalid = -1
    };
    
    
    
        gdb) p _entry_table
        $7 = {0x7f671501e2e0 "H213S2017267J*17267R(+с37236601",
              0x7f671501f060 "H213S2017267J*17267R(+с37236601",
              0x7f6715028d40 "H213K2017267I*XL215t314370h",
              0x7f671502a620 "H213K2017267I*XL215t314370h",
              0x7f6715020180 "H213S2017267J*17267R(+с37236601",
              0x7f6715020f00 "H213S2017267J*17267R(+с37236601",
              0x7f6715021c80 "H213e300H307", <incomplete sequence 360>,
              0x7f6715021c80 "H213e300H307", <incomplete sequence 360>,
              0x7f6715021c80 "H213e300H307", <incomplete sequence 360>,
              0x7f6715021c80 "H213e300H307", <incomplete sequence 360>,
              0x7f6715021c80 "H213e300H307", <incomplete sequence 360>,
              0x7f6715021c80 "H213e300H307", <incomplete sequence 360>,
              0x7f6715021c80 "H213e300H307", <incomplete sequence 360>,
              0x7f6715021f80 "335D$33505V2002322533130133134133735133530033136717207a",
              0x7f6715022300 "335D$33505326|2322533130133134133735133530033136717207a",
              0x7f6715022680 "335D$33505Vy2322533130133134133735133530033136717207	",
              0x7f6715022a00 "335D$331341H2033542033534$3053732004$H20330420XI213345377340220220220220@",
              0x7f6715022a40 "305373QD$XI213345377340220220220220314314314314314314314314314314314314314314314314@",
              0x7f6715022a80 "335D$331355331311331361H2033542033534$3053732004$H20330420XI213345377340@",
              0x7f6715022ac0 "335D$331354331311331361H2033542033534$3053732004$H20330420XI21334537734034003",
              0x7f6715022ee0 "335D$335D$3033135633735117207}",
              0x7f6715022b00 "335D$331300H203354233331<$21304$201", <incomplete sequence 310>,
              0x7f6715023420 "H213S2017267J*17267R(+с37236601",
              0x7f67150241a0 "201=6C0126",
              0x7f6715025ac0 "201=26*0126",
              0x7f6715027400 "201=326200126"}
    
                (gdb) p k
        $3 = AbstractInterpreter::zerolocals
                (gdb) p/d k
        $4 = 0
                三层关系
    -------------第一层-----------------
        (gdb) p h_method._value
        $7 = (Method *) 0x7f2908a13938
                (gdb) p * h_method._value
        $8 = (Method) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
                            _valid = 0
                },
                members of Method:
                _constMethod = 0x7f2908a138c0,
                _method_data = 0x0,
                _method_counters = 0x0,
                _access_flags = {
                    _flags = 138
                },
                _vtable_index = -3,
                _method_size = 12,
                _intrinsic_id = 0 '00',
                _jfr_towrite = 0 '00',
                _caller_sensitive = 0 '00',
                _force_inline = 0 '00',
                _hidden = 0 '00',
                _dont_inline = 0 '00',
                _compiled_invocation_count = 0,
                _i2i_entry = 0x0,
                _adapter = 0x0,
                _from_compiled_entry = 0x0,
                _code = 0x0,
                _from_interpreted_entry = 0x0,
                static extra_stack_entries_for_jsr292 = 1
        }
    -------------第二层-----------------
        (gdb) p *h_method._value._constMethod
        $10 = {
                <MetaspaceObj> = {<No data fields>},
                members of ConstMethod:
                _fingerprint = 9223372036854775808,
                _constants = 0x7f2908a110e0,
                _stackmap_data = 0x0,
                _constMethod_size = 15,
                _flags = 5,
                _code_size = 22,
                _name_index = 330,
                _signature_index = 331,
                _method_idnum = 27,
                _max_stack = 2,
                _max_locals = 3,
                _size_of_parameters = 2,
                static MAX_IDNUM = 65534,
                static UNSET_IDNUM = 65535
        }
     -------------第三层-----------------
        (gdb) p *h_method._value._constMethod._constants
        $9 = (ConstantPool) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fce1070 <vtable for ConstantPool+16>,
                            _valid = 0
                },
                members of ConstantPool:
                _tags = 0x7f2908a10db0,
                _cache = 0x7f2908a14e30,
                _pool_holder = 0x100038f38,
                _operands = 0x0,
                _resolved_references = 0x7f29180e0d60,
                _reference_map = 0x7f2908a15dc0,
                _flags = 0,
                _length = 809,
                _saved = {
                    _resolved_reference_length = 0,
                            _version = 0
                },
                _lock = 0x7f29181535c8
        }
    
    查看自己写的Test类
        (gdb) p * m._value
        $15 = (Method) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
                            _valid = 0
                },
                members of Method:
                _constMethod = 0x7f2908c00588,
                _method_data = 0x0,
                _method_counters = 0x0,
                _access_flags = {
                    _flags = 9
                },
                _vtable_index = -3,
                _method_size = 12,
                _intrinsic_id = 0 '00',
                _jfr_towrite = 0 '00',
                _caller_sensitive = 0 '00',
                _force_inline = 0 '00',
                _hidden = 0 '00',
                _dont_inline = 0 '00',
                _compiled_invocation_count = 0,
                _i2i_entry = 0x0,
                _adapter = 0x0,
                _from_compiled_entry = 0x0,
                _code = 0x0,
                _from_interpreted_entry = 0x0,
                static extra_stack_entries_for_jsr292 = 1
        }
    
    
        (gdb) p * m._value._constMethod
        $16 = {
                <MetaspaceObj> = {<No data fields>},
                members of ConstMethod:
                _fingerprint = 9223372036854775808,
                _constants = 0x7f2908c00080,
                _stackmap_data = 0x7f2908c006d8,
                _constMethod_size = 30,
                _flags = 5,
                _code_size = 81,
                _name_index = 29,
                _signature_index = 30,
                _method_idnum = 3,
                _max_stack = 4,
                _max_locals = 8,
                _size_of_parameters = 1,
                static MAX_IDNUM = 65534,
                static UNSET_IDNUM = 65535
        }
    
        这个是_name_index = 29, 29 是main方法
        (gdb) p k
        $18 = AbstractInterpreter::zerolocals
        _entry_table[k] =0x7f290901e2e0
        set_interpreter_entry(entry);设置;之前
        (gdb) p * this
        $21 = (Method) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
                            _valid = 0
                },
                members of Method:
                _constMethod = 0x7f2908c00588,
                _method_data = 0x0,
                _method_counters = 0x0,
                _access_flags = {
                    _flags = 9
                },
                _vtable_index = -3,
                _method_size = 12,
                _intrinsic_id = 0 '00',
                _jfr_towrite = 0 '00',
                _caller_sensitive = 0 '00',
                _force_inline = 0 '00',
                _hidden = 0 '00',
                _dont_inline = 0 '00',
                _compiled_invocation_count = 0,
                _i2i_entry = 0x0,
                _adapter = 0x0,
                _from_compiled_entry = 0x0,
                _code = 0x0,
                _from_interpreted_entry = 0x0,
                static extra_stack_entries_for_jsr292 = 1
        }
    设置之后
        (gdb) p * this
        $23 = (Method) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
                            _valid = 0
                },
                members of Method:
                _constMethod = 0x7f2908c00588,
                _method_data = 0x0,
                _method_counters = 0x0,
                _access_flags = {
                    _flags = 9
                },
                _vtable_index = -3,
                _method_size = 12,
                _intrinsic_id = 0 '00',
                _jfr_towrite = 0 '00',
                _caller_sensitive = 0 '00',
                _force_inline = 0 '00',
                _hidden = 0 '00',
                _dont_inline = 0 '00',
                _compiled_invocation_count = 0,
                _i2i_entry = 0x7f290901e2e0 "H213S2017267J*17267R(+с37236601",  //设置了这个
                _adapter = 0x0,
                _from_compiled_entry = 0x0,
                _code = 0x0,
                _from_interpreted_entry = 0x7f290901e2e0 "H213S2017267J*17267R(+с37236601",//设置了这个
                static extra_stack_entries_for_jsr292 = 1
        }
    
        address Method::make_adapters(methodHandle mh, TRAPS) {
            // Adapters for compiled code are made eagerly here.  They are fairly
            // small (generally < 100 bytes) and quick to make (and cached and shared)
            // so making them eagerly shouldn't be too expensive.
            AdapterHandlerEntry* adapter = AdapterHandlerLibrary::get_adapter(mh);
            if (adapter == NULL ) {
                THROW_MSG_NULL(vmSymbols::java_lang_VirtualMachineError(), "out of space in CodeCache for adapters");
            }
    
            mh->set_adapter_entry(adapter);
            mh->_from_compiled_entry = adapter->get_c2i_entry();
            return adapter->get_c2i_entry();
        }
    
        查看adapter
        $31 = (AdapterHandlerEntry *) 0x7f29180aee10
        (gdb) x/8xg adapter
        0x7f29180aee10:    0xf1f1f1f1f1f1f1f1    0xf1f1f1f1b0000000
        0x7f29180aee20:    0x0000000000000000    0x00007f2918087c98  //第一个成员变量_fingerprint
        0x7f29180aee30:    0x00007f2909106ae0    0x00007f2909106bf4 c2i
        0x7f29180aee40:    0x00007f2909106bc7    0x0000000000000000
    
    
                (gdb) p mh->_from_compiled_entry
        $30 = (volatile address) 0x7f2909106bf4 "H201{P"
    
                (gdb) x/120i 0x00007f2909106ae0
        0x7f2909106ae0:    mov    (%rsp),%rax
        0x7f2909106ae4:    movabs $0x7f29090053e0,%r11
        0x7f2909106aee:    cmp    %r11,%rax
        0x7f2909106af1:    jbe    0x7f2909106b0a
        0x7f2909106af7:    movabs $0x7f29091053e0,%r11
        0x7f2909106b01:    cmp    %r11,%rax
        0x7f2909106b04:    jb     0x7f2909106ba7
        0x7f2909106b0a:    movabs $0x7f2909000420,%r11
        0x7f2909106b14:    cmp    %r11,%rax
        0x7f2909106b17:    jbe    0x7f2909106b30
        0x7f2909106b1d:    movabs $0x7f2909004e58,%r11
        0x7f2909106b27:    cmp    %r11,%rax
        0x7f2909106b2a:    jb     0x7f2909106ba7
        0x7f2909106b30:    mov    %rsp,-0x28(%rsp)
        0x7f2909106b35:    sub    $0x80,%rsp
        0x7f2909106b3c:    mov    %rax,0x78(%rsp)
        0x7f2909106b41:    mov    %rcx,0x70(%rsp)
        0x7f2909106b46:    mov    %rdx,0x68(%rsp)
        0x7f2909106b4b:    mov    %rbx,0x60(%rsp)
        0x7f2909106b50:    mov    %rbp,0x50(%rsp)
        0x7f2909106b55:    mov    %rsi,0x48(%rsp)
        0x7f2909106b5a:    mov    %rdi,0x40(%rsp)
        0x7f2909106b5f:    mov    %r8,0x38(%rsp)
        0x7f2909106b64:    mov    %r9,0x30(%rsp)
        0x7f2909106b69:    mov    %r10,0x28(%rsp)
        0x7f2909106b6e:    mov    %r11,0x20(%rsp)
        0x7f2909106b73:    mov    %r12,0x18(%rsp)
        0x7f2909106b78:    mov    %r13,0x10(%rsp)
        0x7f2909106b7d:    mov    %r14,0x8(%rsp)
        0x7f2909106b82:    mov    %r15,(%rsp)
        0x7f2909106b86:    movabs $0x7f291f7bd600,%rdi
        0x7f2909106b90:    movabs $0x7f2909106b30,%rsi
        0x7f2909106b9a:    mov    %rsp,%rdx
        0x7f2909106b9d:    and    $0xfffffffffffffff0,%rsp
        0x7f2909106ba1:    callq  0x7f291f238dc8 <MacroAssembler::debug64(char*, long, long*)>
                                  0x7f2909106ba6:    hlt
        0x7f2909106ba7:    mov    %rsp,%r11
        0x7f2909106baa:    and    $0xfffffffffffffff0,%rsp
        0x7f2909106bae:    push   %rax
        0x7f2909106baf:    mov    %r11,%rax
        0x7f2909106bb2:    mov    0x48(%rbx),%r11
        0x7f2909106bb6:    mov    0x8(%rax),%rsi
        0x7f2909106bba:    mov    %rbx,0x248(%r15)
        0x7f2909106bc1:    mov    %rbx,%rax
        0x7f2909106bc4:    jmpq   *%r11
        0x7f2909106bc7:    mov    0x8(%rsi),%ebx
        0x7f2909106bca:    shl    $0x3,%rbx
        0x7f2909106bce:    cmp    0x10(%rax),%rbx
        0x7f2909106bd2:    mov    0x8(%rax),%rbx
        0x7f2909106bd6:    je     0x7f2909106be1
        0x7f2909106bdc:    jmpq   0x7f2909105be0
        0x7f2909106be1:    cmpq   $0x0,0x50(%rbx)
        0x7f2909106be9:    je     0x7f2909106ce4
        0x7f2909106bef:    jmpq   0x7f2909105be0
        0x7f2909106bf4:    cmpq   $0x0,0x50(%rbx)
        0x7f2909106bfc:    je     0x7f2909106ce4
        0x7f2909106c02:    mov    %rsp,%r13
        0x7f2909106c05:    mov    (%rsp),%rax
        0x7f2909106c09:    and    $0xfffffffffffffff0,%rsp
        0x7f2909106c0d:    pushfq
        0x7f2909106c0e:    sub    $0x8,%rsp
        0x7f2909106c12:    mov    %rsp,-0x28(%rsp)
        0x7f2909106c17:    sub    $0x80,%rsp
        0x7f2909106c1e:    mov    %rax,0x78(%rsp)
        0x7f2909106c23:    mov    %rcx,0x70(%rsp)
        0x7f2909106c28:    mov    %rdx,0x68(%rsp)
        0x7f2909106c2d:    mov    %rbx,0x60(%rsp)
        0x7f2909106c32:    mov    %rbp,0x50(%rsp)
        0x7f2909106c37:    mov    %rsi,0x48(%rsp)
        0x7f2909106c3c:    mov    %rdi,0x40(%rsp)
        0x7f2909106c41:    mov    %r8,0x38(%rsp)
        0x7f2909106c46:    mov    %r9,0x30(%rsp)
        0x7f2909106c4b:    mov    %r10,0x28(%rsp)
        0x7f2909106c50:    mov    %r11,0x20(%rsp)
        0x7f2909106c55:    mov    %r12,0x18(%rsp)
        0x7f2909106c5a:    mov    %r13,0x10(%rsp)
        0x7f2909106c5f:    mov    %r14,0x8(%rsp)
        0x7f2909106c64:    mov    %r15,(%rsp)
        0x7f2909106c68:    sub    $0x200,%rsp
        0x7f2909106c6f:    fxsave64 (%rsp)
        0x7f2909106c74:    mov    %rbx,%rdi
        0x7f2909106c77:    mov    %rax,%rsi
        0x7f2909106c7a:    callq  0x7f291f3d3a32 <SharedRuntime::fixup_callers_callsite(Method*, unsigned char*)>
                                  0x7f2909106c7f:    fxrstor64 (%rsp)
        0x7f2909106c84:    add    $0x200,%rsp
        0x7f2909106c8b:    mov    (%rsp),%r15
        0x7f2909106c8f:    mov    0x8(%rsp),%r14
        0x7f2909106c94:    mov    0x10(%rsp),%r13
        0x7f2909106c99:    mov    0x18(%rsp),%r12
        0x7f2909106c9e:    mov    0x20(%rsp),%r11
        0x7f2909106ca3:    mov    0x28(%rsp),%r10
        0x7f2909106ca8:    mov    0x30(%rsp),%r9
        0x7f2909106cad:    mov    0x38(%rsp),%r8
        0x7f2909106cb2:    mov    0x40(%rsp),%rdi
        0x7f2909106cb7:    mov    0x48(%rsp),%rsi
        0x7f2909106cbc:    mov    0x50(%rsp),%rbp
        0x7f2909106cc1:    mov    0x60(%rsp),%rbx
        0x7f2909106cc6:    mov    0x68(%rsp),%rdx
        0x7f2909106ccb:    mov    0x70(%rsp),%rcx
        0x7f2909106cd0:    mov    0x78(%rsp),%rax
        0x7f2909106cd5:    add    $0x80,%rsp
        0x7f2909106cdc:    add    $0x8,%rsp
        0x7f2909106ce0:    popfq
        0x7f2909106ce1:    mov    %r13,%rsp
        0x7f2909106ce4:    pop    %rax
        0x7f2909106ce5:    mov    %rsp,%r13
        0x7f2909106ce8:    sub    $0x10,%rsp
        0x7f2909106cec:    mov    %rax,(%rsp)
        0x7f2909106cf0:    mov    %rsi,0x8(%rsp)
        0x7f2909106cf5:    mov    0x38(%rbx),%rcx
        0x7f2909106cf9:    jmpq   *%rcx
        0x7f2909106cfb:    hlt
        0x7f2909106cfc:    hlt
        0x7f2909106cfd:    hlt
        0x7f2909106cfe:    hlt
        0x7f2909106cff:    hlt
        0x7f2909106d00:    or     %al,(%rax)
        0x7f2909106d02:    add    %al,(%rax)
        0x7f2909106d04:    add    %al,(%rax)
        0x7f2909106d06:    add    %al,(%rax)
    
        这个上面已经分析过了,这里省略了...
        设置完成了i2i
        (gdb) p m._value
        $33 = (Method *) 0x7f2908c00678
                (gdb) p * m._value
        $34 = (Method) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
                            _valid = 0
                },
                members of Method:
                _constMethod = 0x7f2908c00588,
                _method_data = 0x0,
                _method_counters = 0x0,
                _access_flags = {
                    _flags = 9
                },
                _vtable_index = -3,
                _method_size = 12,
                _intrinsic_id = 0 '00',
                _jfr_towrite = 0 '00',
                _caller_sensitive = 0 '00',
                _force_inline = 0 '00',
                _hidden = 0 '00',
                _dont_inline = 0 '00',
                _compiled_invocation_count = 0,
                _i2i_entry = 0x7f290901e2e0 "H213S2017267J*17267R(+с37236601",
                _adapter = 0x7f29180aee10,
                _from_compiled_entry = 0x7f2909106bf4 "H201{P",   //就是这里设置了compiled_entry取值是从adapter中拿到的
    
                _code = 0x0,
                _from_interpreted_entry = 0x7f290901e2e0 "H213S2017267J*17267R(+с37236601",
                static extra_stack_entries_for_jsr292 = 1
        }
    
        循环第2个
        (gdb) p * m._value._constMethod
        $35 = {
                <MetaspaceObj> = {<No data fields>},
                members of ConstMethod:
                _fingerprint = 9223372036854775808,
                _constants = 0x7f2908c00080,
                _stackmap_data = 0x0,
                _constMethod_size = 7,
                _flags = 1,
                _code_size = 6,
                _name_index = 10,
                _signature_index = 11,
                _method_idnum = 2,
                _max_stack = 1,
                _max_locals = 0,
                _size_of_parameters = 0,
                static MAX_IDNUM = 65534,
                static UNSET_IDNUM = 65535
        }
    查看_name_index = 10, 知道是clint方法
    设置之前
        (gdb) p this
        $37 = (Method * const) 0x7f2908c003b0
                (gdb) p * this
        $38 = (Method) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
                            _valid = 0
                },
                members of Method:
                _constMethod = 0x7f2908c00378,
                _method_data = 0x0,
                _method_counters = 0x0,
                _access_flags = {
                    _flags = 8
                },
                _vtable_index = -3,
                _method_size = 12,
                _intrinsic_id = 0 '00',
                _jfr_towrite = 0 '00',
                _caller_sensitive = 0 '00',
                _force_inline = 0 '00',
                _hidden = 0 '00',
                _dont_inline = 0 '00',
                _compiled_invocation_count = 0,
                _i2i_entry = 0x0,
                _adapter = 0x0,
                _from_compiled_entry = 0x0,
                _code = 0x0,
                _from_interpreted_entry = 0x0,
                static extra_stack_entries_for_jsr292 = 1
        }
    
        第3个循环
        (gdb) p * this
        $40 = (Method) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
                            _valid = 0
                },
                members of Method:
                _constMethod = 0x7f2908c00410,
                _method_data = 0x0,
                _method_counters = 0x0,
                _access_flags = {
                    _flags = 1
                },
                _vtable_index = -3,
                _method_size = 12,
                _intrinsic_id = 0 '00',
                _jfr_towrite = 0 '00',
                _caller_sensitive = 0 '00',
                _force_inline = 0 '00',
                _hidden = 0 '00',
                _dont_inline = 0 '00',
                _compiled_invocation_count = 0,
                _i2i_entry = 0x0,
                _adapter = 0x0,
                _from_compiled_entry = 0x0,
                _code = 0x0,
                _from_interpreted_entry = 0x0,
                static extra_stack_entries_for_jsr292 = 1
        }
        (gdb) p * this._constMethod
        $41 = {
                <MetaspaceObj> = {<No data fields>},
                members of ConstMethod:
                _fingerprint = 9223372036854775808,
                _constants = 0x7f2908c00080,
                _stackmap_data = 0x0,
                _constMethod_size = 14,
                _flags = 5,
                _code_size = 15,
                _name_index = 17,
                _signature_index = 18,
                _method_idnum = 1,
                _max_stack = 2,
                _max_locals = 3,
                _size_of_parameters = 3,
                static MAX_IDNUM = 65534,
                static UNSET_IDNUM = 65535
        }
    
        _name_index = 17, 查看常量池是init方法
     设置之后
     $46 = (Method *) 0x7f2908c00480
             (gdb) p * mh._value
        $47 = (Method) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
                            _valid = 0
                },
                members of Method:
                _constMethod = 0x7f2908c00410,
                _method_data = 0x0,
                _method_counters = 0x0,
                _access_flags = {
                    _flags = 1
                },
                _vtable_index = -3,
                _method_size = 12,
                _intrinsic_id = 0 '00',
                _jfr_towrite = 0 '00',
                _caller_sensitive = 0 '00',
                _force_inline = 0 '00',
                _hidden = 0 '00',
                _dont_inline = 0 '00',
                _compiled_invocation_count = 0,
                _i2i_entry = 0x7f290901e2e0 "H213S2017267J*17267R(+с37236601",
                _adapter = 0x7f29180b0048, //这个每个方法都不一样的
                _from_compiled_entry = 0x7f2909125a21 "H201{P",
                _code = 0x0,
                _from_interpreted_entry = 0x7f290901e2e0 "H213S2017267J*17267R(+с37236601",
                static extra_stack_entries_for_jsr292 = 1
        }
    
        地4个循环
        (gdb) p * this
        $52 = (Method) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
                            _valid = 0
                },
                members of Method:
                _constMethod = 0x7f2908c004e0,
                _method_data = 0x0,
                _method_counters = 0x0,
                _access_flags = {
                    _flags = 1
                },
                _vtable_index = -3,
                _method_size = 12,
                _intrinsic_id = 0 '00',
                _jfr_towrite = 0 '00',
                _caller_sensitive = 0 '00',
                _force_inline = 0 '00',
                _hidden = 0 '00',
                _dont_inline = 0 '00',
                _compiled_invocation_count = 0,
                _i2i_entry = 0x0,
                _adapter = 0x0,
                _from_compiled_entry = 0x0,
                _code = 0x0,
                _from_interpreted_entry = 0x0,
                static extra_stack_entries_for_jsr292 = 1
        }
    
        执行之后
        (gdb) p *m._value
        $55 = (Method) {
                <Metadata> = {
                    <MetaspaceObj> = {<No data fields>},
                    members of Metadata:
                    _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
                            _valid = 0
                },
                members of Method:
                _constMethod = 0x7f2908c004e0,
                _method_data = 0x0,
                _method_counters = 0x0,
                _access_flags = {
                    _flags = 1
                },
                _vtable_index = -3,
                _method_size = 12,
                _intrinsic_id = 0 '00',
                _jfr_towrite = 0 '00',
                _caller_sensitive = 0 '00',
                _force_inline = 0 '00',
                _hidden = 0 '00',
                _dont_inline = 0 '00',
                _compiled_invocation_count = 0,
                _i2i_entry = 0x7f290901e2e0 "H213S2017267J*17267R(+с37236601",
                _adapter = 0x7f29180aee10,//这个值不同呢
    
                _from_compiled_entry = 0x7f2909106bf4 "H201{P",
                _code = 0x0,
                _from_interpreted_entry = 0x7f290901e2e0 "H213S2017267J*17267R(+с37236601",
                static extra_stack_entries_for_jsr292 = 1
        }

    这里就比较清楚了,这个过程,,其中之前不理解的是栈帧重用,这里将main方法的操作数栈,作为了init方法的arg1,arg2,等本地变量表

  • 相关阅读:
    创建类以及引用一个类
    修改hosts文件
    微信第三方登录接口开发
    Android定位
    Leetcode 102. Binary Tree Level Order Traversal
    Leetcode 725. Split Linked List in Parts
    Leetcode 445. Add Two Numbers II
    Leetcode 328. Odd Even Linked List
    Leetcode 237. Delete Node in a Linked List
    Leetcode 234. Palindrome Linked List
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/14710372.html
Copyright © 2011-2022 走看看