jvm源码解读--12 invokspecial指令的解读
阅读原文时间:2022年03月03日阅读:3

先看代码

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
3 dup
4 invokespecial #7 >
7 astore_1
8 aload_1
9 invokevirtual #8
12 new #6
15 dup
16 invokespecial #7 >
19 astore_2
20 aload_2
21 invokevirtual #9
24 aload_2
25 invokespecial #10
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 "H\\213S\\020\\017\\267J\*\\017\\267R(+с\\372\\366\\001",  
      0x7f671501f060 "H\\213S\\020\\017\\267J\*\\017\\267R(+с\\372\\366\\001",  
      0x7f6715028d40 "H\\213K\\020\\017\\267I\*XL\\215t\\314\\370h",  
      0x7f671502a620 "H\\213K\\020\\017\\267I\*XL\\215t\\314\\370h",  
      0x7f6715020180 "H\\213S\\020\\017\\267J\*\\017\\267R(+с\\372\\366\\001",  
      0x7f6715020f00 "H\\213S\\020\\017\\267J\*\\017\\267R(+с\\372\\366\\001",  
      0x7f6715021c80 "H\\213e\\300H\\307", <incomplete sequence \\360>,  
      0x7f6715021c80 "H\\213e\\300H\\307", <incomplete sequence \\360>,  
      0x7f6715021c80 "H\\213e\\300H\\307", <incomplete sequence \\360>,  
      0x7f6715021c80 "H\\213e\\300H\\307", <incomplete sequence \\360>,  
      0x7f6715021c80 "H\\213e\\300H\\307", <incomplete sequence \\360>,  
      0x7f6715021c80 "H\\213e\\300H\\307", <incomplete sequence \\360>,  
      0x7f6715021c80 "H\\213e\\300H\\307", <incomplete sequence \\360>,  
      0x7f6715021f80 "\\335D$\\b\\335\\005V\\200\\232\\025\\331\\301\\331\\341\\337\\351\\335\\300\\331\\367\\017\\207\\a",  
      0x7f6715022300 "\\335D$\\b\\335\\005\\326|\\232\\025\\331\\301\\331\\341\\337\\351\\335\\300\\331\\367\\017\\207\\a",  
      0x7f6715022680 "\\335D$\\b\\335\\005Vy\\232\\025\\331\\301\\331\\341\\337\\351\\335\\300\\331\\367\\017\\207\\t",  
      0x7f6715022a00 "\\335D$\\b\\331\\341H\\203\\354\\020\\335\\034$\\305\\373\\020\\004$H\\203\\304\\020XI\\213\\345\\377\\340\\220\\220\\220\\220@",  
      0x7f6715022a40 "\\305\\373QD$\\bXI\\213\\345\\377\\340\\220\\220\\220\\220\\314\\314\\314\\314\\314\\314\\314\\314\\314\\314\\314\\314\\314\\314\\314\\314@",  
      0x7f6715022a80 "\\335D$\\b\\331\\355\\331\\311\\331\\361H\\203\\354\\020\\335\\034$\\305\\373\\020\\004$H\\203\\304\\020XI\\213\\345\\377\\340@",  
      0x7f6715022ac0 "\\335D$\\b\\331\\354\\331\\311\\331\\361H\\203\\354\\020\\335\\034$\\305\\373\\020\\004$H\\203\\304\\020XI\\213\\345\\377\\340\\340\\003",  
      0x7f6715022ee0 "\\335D$\\b\\335D$\\030\\331\\356\\337\\351\\017\\207}",  
      0x7f6715022b00 "\\335D$\\b\\331\\300H\\203\\354\\b\\233\\331<$\\213\\004$\\201", <incomplete sequence \\310>,  
      0x7f6715023420 "H\\213S\\020\\017\\267J\*\\017\\267R(+с\\372\\366\\001",  
      0x7f67150241a0 "\\201=6C\\001\\026",  
      0x7f6715025ac0 "\\201=\\026\*\\001\\026",  
      0x7f6715027400 "\\201=\\326\\020\\001\\026"}

        (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) {
= {
= {},
members of Metadata:
_vptr.Metadata = 0x7f291fcf1b90 ,
_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 '\000',
_jfr_towrite = 0 '\000',
_caller_sensitive = 0 '\000',
_force_inline = 0 '\000',
_hidden = 0 '\000',
_dont_inline = 0 '\000',
_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 = {
= {},
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) {
= {
= {},
members of Metadata:
_vptr.Metadata = 0x7f291fce1070 ,
_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) {
= {
= {},
members of Metadata:
_vptr.Metadata = 0x7f291fcf1b90 ,
_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 '\000',
_jfr_towrite = 0 '\000',
_caller_sensitive = 0 '\000',
_force_inline = 0 '\000',
_hidden = 0 '\000',
_dont_inline = 0 '\000',
_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 '\\000',  
        \_jfr\_towrite = 0 '\\000',  
        \_caller\_sensitive = 0 '\\000',  
        \_force\_inline = 0 '\\000',  
        \_hidden = 0 '\\000',  
        \_dont\_inline = 0 '\\000',  
        \_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) {
= {
= {},
members of Metadata:
_vptr.Metadata = 0x7f291fcf1b90 ,
_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 '\000',
_jfr_towrite = 0 '\000',
_caller_sensitive = 0 '\000',
_force_inline = 0 '\000',
_hidden = 0 '\000',
_dont_inline = 0 '\000',
_compiled_invocation_count = 0,
_i2i_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001", //设置了这个
_adapter = 0x0,
_from_compiled_entry = 0x0,
_code = 0x0,
_from_interpreted_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",//设置了这个
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 "H\\201{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 '\\000',  
        \_jfr\_towrite = 0 '\\000',  
        \_caller\_sensitive = 0 '\\000',  
        \_force\_inline = 0 '\\000',  
        \_hidden = 0 '\\000',  
        \_dont\_inline = 0 '\\000',  
        \_compiled\_invocation\_count = 0,  
        \_i2i\_entry = 0x7f290901e2e0 "H\\213S\\020\\017\\267J\*\\017\\267R(+с\\372\\366\\001",  
        \_adapter = 0x7f29180aee10,  
        \_from\_compiled\_entry = 0x7f2909106bf4 "H\\201{P",   //就是这里设置了compiled\_entry取值是从adapter中拿到的

        \_code = 0x0,  
        \_from\_interpreted\_entry = 0x7f290901e2e0 "H\\213S\\020\\017\\267J\*\\017\\267R(+с\\372\\366\\001",  
        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) {
= {
= {},
members of Metadata:
_vptr.Metadata = 0x7f291fcf1b90 ,
_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 '\000',
_jfr_towrite = 0 '\000',
_caller_sensitive = 0 '\000',
_force_inline = 0 '\000',
_hidden = 0 '\000',
_dont_inline = 0 '\000',
_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 '\\000',  
        \_jfr\_towrite = 0 '\\000',  
        \_caller\_sensitive = 0 '\\000',  
        \_force\_inline = 0 '\\000',  
        \_hidden = 0 '\\000',  
        \_dont\_inline = 0 '\\000',  
        \_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) {
= {
= {},
members of Metadata:
_vptr.Metadata = 0x7f291fcf1b90 ,
_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 '\000',
_jfr_towrite = 0 '\000',
_caller_sensitive = 0 '\000',
_force_inline = 0 '\000',
_hidden = 0 '\000',
_dont_inline = 0 '\000',
_compiled_invocation_count = 0,
_i2i_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
_adapter = 0x7f29180b0048, //这个每个方法都不一样的
_from_compiled_entry = 0x7f2909125a21 "H\201{P",
_code = 0x0,
_from_interpreted_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
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 '\\000',  
        \_jfr\_towrite = 0 '\\000',  
        \_caller\_sensitive = 0 '\\000',  
        \_force\_inline = 0 '\\000',  
        \_hidden = 0 '\\000',  
        \_dont\_inline = 0 '\\000',  
        \_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 '\\000',  
        \_jfr\_towrite = 0 '\\000',  
        \_caller\_sensitive = 0 '\\000',  
        \_force\_inline = 0 '\\000',  
        \_hidden = 0 '\\000',  
        \_dont\_inline = 0 '\\000',  
        \_compiled\_invocation\_count = 0,  
        \_i2i\_entry = 0x7f290901e2e0 "H\\213S\\020\\017\\267J\*\\017\\267R(+с\\372\\366\\001",  
        \_adapter = 0x7f29180aee10,//这个值不同呢

        \_from\_compiled\_entry = 0x7f2909106bf4 "H\\201{P",  
        \_code = 0x0,  
        \_from\_interpreted\_entry = 0x7f290901e2e0 "H\\213S\\020\\017\\267J\*\\017\\267R(+с\\372\\366\\001",  
        static extra\_stack\_entries\_for\_jsr292 = 1  
}

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