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,等本地变量表

  • 相关阅读:
    常见水果的日语单词汇总
    身体各个部位的日语单词
    多拉A梦——日语歌词
    日语——动词的各种变形
    语言类型学分类
    常用自定义函数
    IOS 读取xib里的子控件
    IOS中 copy ,strong ,weak ,assign使用区别
    IOS 字典转模型
    IOS 纯代码添加 Button Image Label 添加到自定义View中
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/14710372.html
Copyright © 2011-2022 走看看