先看代码

  1. package com.zyt.jvmbook;
  2.  
  3. public class Girl extends Person{
  4. public Girl() {
  5. int a;
  6. }
  7.  
  8. @Override
  9. public void sayHello() {
  10. System.out.println("girl say hello");
  11. }
  12. private void sayHi(){
  13. System.out.println("hellow");
  14. }
  15.  
  16. public static void main(String[] args) {
  17. Person p = new Girl();
  18.  
  19. p.sayHello();
  20. Girl g=new Girl();
  21. g.sayHello();
  22. g.sayHi();
  23.  
  24. }
  25. }

查看编译后的内容

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

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

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

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

///////高地址

oop

oop

//低地址

那么贴出invokespecail指令

  1. ----------------------------------------------------------------------
  2. invokespecial 183 invokespecial [0x0000000002cf1da0, 0x0000000002cf2040] 672 bytes
  3.  
  4. 0x0000000002cf1da0: push %rax
  5. 0x0000000002cf1da1: jmpq 0x0000000002cf1dd0
  6. 0x0000000002cf1da6: sub $0x8,%rsp
  7. 0x0000000002cf1daa: vmovss %xmm0,(%rsp)
  8. 0x0000000002cf1daf: jmpq 0x0000000002cf1dd0
  9. 0x0000000002cf1db4: sub $0x10,%rsp
  10. 0x0000000002cf1db8: vmovsd %xmm0,(%rsp)
  11. 0x0000000002cf1dbd: jmpq 0x0000000002cf1dd0
  12. 0x0000000002cf1dc2: sub $0x10,%rsp
  13. 0x0000000002cf1dc6: mov %rax,(%rsp)
  14. 0x0000000002cf1dca: jmpq 0x0000000002cf1dd0
  15.  
  16. 0x0000000002cf1dcf: push %rax
  17. 开始执行.有栈顶缓存,即rax中有值
  18. // void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
  19. // int bcp_offset,
  20. // size_t index_size) {
  21. // assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
  22. // if (index_size == sizeof(u2)) {
  23. // load_unsigned_short(index, Address(r13, bcp_offset));}
  24. 0x0000000002cf1dd0: mov %r13,-0x38(%rbp) //bcp的地址
  25. 0x0000000002cf1dd4: movzwl 0x1(%r13),%edx
  26. 0x0000000002cf1dd9: mov -0x28(%rbp),%rcx cache放到rcx
  27. 0x0000000002cf1ddd: shl $0x2,%edx
  28. //movl(bytecode, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()));
  29. //那么cache就是rcx,index就是rdx
  30. 0x0000000002cf1de0: mov 0x10(%rcx,%rdx,8),%ebx 取得cache_indices的, 0x10 + rcx + rdx*8
  31. // const int shift_count = (1 + byte_no) * BitsPerByte;
  32.  
  33. // shrl(bytecode, shift_count);
  34. 0x0000000002cf1de4: shr $0x10,%ebx
  35. 0x0000000002cf1de7: and $0xff,%ebx
  36. 0x0000000002cf1ded: cmp $0xb7,%ebx
  37. 0x0000000002cf1df3: je 0x0000000002cf1e9a
  38. //验证时否为0xb7
  39. //在invokevirtual、invokespecial等字节码指令对应的汇编片段中,如果_indices中的b2或b1不为字节码指令的操作码,
  40. // 说明方法还没有连接,需要调用InterpreterRuntime::resolve_invoke()方法生成ConstantPoolCacheEntry。
  41. ---解析ConstantPoolCacheEntry---开始
  42. 0x0000000002cf1df9: mov $0xb7,%ebx
  43. 0x0000000002cf1dfe: callq 0x0000000002cf1e08
  44.  
  45. 0x0000000002cf1e03: jmpq 0x0000000002cf1e8e
  46. 0x0000000002cf1e08: mov %rbx,%rdx
  47. 0x0000000002cf1e0b: lea 0x8(%rsp),%rax
  48. 0x0000000002cf1e10: mov %r13,-0x38(%rbp)
  49. 0x0000000002cf1e14: mov %r15,%rcx
  50. 0x0000000002cf1e17: mov %rbp,0x1e8(%r15)
  51. 0x0000000002cf1e1e: mov %rax,0x1d8(%r15)
  52. 0x0000000002cf1e25: sub $0x20,%rsp
  53. 0x0000000002cf1e29: test $0xf,%esp
  54. 0x0000000002cf1e2f: je 0x0000000002cf1e47
  55. 0x0000000002cf1e35: sub $0x8,%rsp
  56. 0x0000000002cf1e39: callq 0x000000005449a3c0
  57. 0x0000000002cf1e3e: add $0x8,%rsp
  58. 0x0000000002cf1e42: jmpq 0x0000000002cf1e4c
  59. 0x0000000002cf1e47: callq 0x000000005449a3c0
  60. 0x0000000002cf1e4c: add $0x20,%rsp
  61. 0x0000000002cf1e50: movabs $0x0,%r10
  62. 0x0000000002cf1e5a: mov %r10,0x1d8(%r15)
  63. 0x0000000002cf1e61: movabs $0x0,%r10
  64. 0x0000000002cf1e6b: mov %r10,0x1e8(%r15)
  65. 0x0000000002cf1e72: cmpq $0x0,0x8(%r15)
  66. 0x0000000002cf1e7a: je 0x0000000002cf1e85
  67. 0x0000000002cf1e80: jmpq 0x0000000002cd07e0
  68. 0x0000000002cf1e85: mov -0x38(%rbp),%r13
  69. 0x0000000002cf1e89: mov -0x30(%rbp),%r14
  70. 0x0000000002cf1e8d: retq
  71. 0x0000000002cf1e8e: movzwl 0x1(%r13),%edx
  72. 0x0000000002cf1e93: mov -0x28(%rbp),%rcx
  73. 0x0000000002cf1e97: shl $0x2,%edx
  74.  
  75. ---解析ConstantPoolCacheEntry---完成
  76. //__ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
  77. //method_offset=24,取得method
  78. 0x0000000002cf1e9a: mov 0x18(%rcx,%rdx,8),%rbx
  79. // __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset));
  80. //取得flag
  81. //取得flag
  82. 0x0000000002cf1e9f: mov 0x28(%rcx,%rdx,8),%edx
  83. // if (load_receiver) {
  84. // __ movl(recv, flags);
  85. 0x0000000002cf1ea3: mov %edx,%ecx
  86. // __ andl(recv, ConstantPoolCacheEntry::parameter_size_mask);
  87. 0x0000000002cf1ea5: and $0xff,%ecx
  88. // __ movptr(recv, recv_addr);
  89. 0x0000000002cf1eab: mov -0x8(%rsp,%rcx,8),%rcx //-0x8 + rsp+ 8*rcx to rcx;
  90. // // compute return type
  91. //获取tosState
  92. (gdb) p/x _invoke_return_entry
  93. $1 = {0x7f1a6d006e80, 0x7f1a6d006f50, 0x7f1a6d007020,
  94. 0x7f1a6d0070f0, 0x7f1a6d0071c0, 0x7f1a6d007290,
  95. 0x7f1a6d007360, 0x7f1a6d007430, 0x7f1a6d007500}
  96. 0x0000000002cf1eb0: shr $0x1c,%edx
  97. 0x0000000002cf1eb3: movabs $0x54bcbba0,%r10 //_invoke_return_entry
  98. 0x0000000002cf1ebd: mov (%r10,%rdx,8),%rdx 获取返回entry
  99. // __ push(flags);// push return address
  100. 0x0000000002cf1ec1: push %rdx
  101. 0x0000000002cf1ec2: cmp (%rcx),%rax //cache,
  102. // movptr(mdp, Address(rbp, frame::interpreter_frame_mdx_offset * wordSize));
  103. // testptr(mdp, mdp);
  104. // jcc(Assembler::zero, zero_continue);
  105. 0x0000000002cf1ec5: mov -0x20(%rbp),%rax //methodData
  106. 0x0000000002cf1ec9: test %rax,%rax
  107. 0x0000000002cf1ecc: je 0x0000000002cf1ee4
  108. // increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
  109. //
  110. // // The method data pointer needs to be updated to reflect the new target.
  111. // update_mdp_by_constant(mdp, in_bytes(CounterData::counter_data_size()));
  112. // bind(profile_continue);
  113. 0x0000000002cf1ed2: addq $0x1,0x8(%rax)
  114. 0x0000000002cf1ed7: sbbq $0x0,0x8(%rax)
  115. 0x0000000002cf1edc: add $0x10,%rax
  116. 0x0000000002cf1ee0: mov %rax,-0x20(%rbp)
  117.  
  118. 0x0000000002cf1ee4: mov -0x20(%rbp),%rax
  119. 0x0000000002cf1ee8: test %rax,%rax
  120. 0x0000000002cf1eeb: je 0x0000000002cf2020
  121.  
  122. 0x0000000002cf1ef1: cmpb $0xa,-0x10(%rax)
  123. 0x0000000002cf1ef5: jne 0x0000000002cf2020
  124. 0x0000000002cf1efb: add $0x8,%rax
  125. 0x0000000002cf1eff: mov -0x8(%rax),%r13
  126. 0x0000000002cf1f03: sub $0x0,%r13d
  127. 0x0000000002cf1f07: cmp $0x2,%r13d
  128. 0x0000000002cf1f0b: jl 0x0000000002cf2015
  129. 0x0000000002cf1f11: mov 0x8(%rbx),%r13
  130. 0x0000000002cf1f15: movzwl 0x2a(%r13),%r13d
  131. 0x0000000002cf1f1a: sub (%rax),%r13
  132. 0x0000000002cf1f1d: sub $0x1,%r13d
  133. 0x0000000002cf1f21: mov 0x8(%rsp,%r13,8),%r13
  134. 0x0000000002cf1f26: test %r13,%r13
  135. 0x0000000002cf1f29: jne 0x0000000002cf1f35
  136. 0x0000000002cf1f2b: orq $0x1,0x8(%rax)
  137. 0x0000000002cf1f33: jmp 0x0000000002cf1f82
  138. 0x0000000002cf1f35: mov 0x8(%r13),%r13d
  139. 0x0000000002cf1f39: shl $0x3,%r13
  140. 0x0000000002cf1f3d: xor 0x8(%rax),%r13
  141. 0x0000000002cf1f41: test $0xfffffffffffffffc,%r13
  142. 0x0000000002cf1f48: je 0x0000000002cf1f82
  143. 0x0000000002cf1f4a: test $0x2,%r13
  144. 0x0000000002cf1f51: jne 0x0000000002cf1f82
  145. 0x0000000002cf1f53: cmpq $0x0,0x8(%rax)
  146. 0x0000000002cf1f5b: je 0x0000000002cf1f7e
  147. 0x0000000002cf1f5d: cmpq $0x1,0x8(%rax)
  148. 0x0000000002cf1f65: je 0x0000000002cf1f7e
  149. 0x0000000002cf1f67: xor 0x8(%rax),%r13
  150. 0x0000000002cf1f6b: test $0xfffffffffffffffc,%r13
  151. 0x0000000002cf1f72: je 0x0000000002cf1f82
  152. 0x0000000002cf1f74: orq $0x2,0x8(%rax)
  153. 0x0000000002cf1f7c: jmp 0x0000000002cf1f82
  154. 0x0000000002cf1f7e: mov %r13,0x8(%rax)
  155. 0x0000000002cf1f82: add $0x10,%rax
  156. 0x0000000002cf1f86: mov -0x18(%rax),%r13
  157. 0x0000000002cf1f8a: sub $0x2,%r13d
  158. 0x0000000002cf1f8e: cmp $0x2,%r13d
  159. 0x0000000002cf1f92: jl 0x0000000002cf2015
  160. 0x0000000002cf1f98: mov 0x8(%rbx),%r13
  161. 0x0000000002cf1f9c: movzwl 0x2a(%r13),%r13d
  162. 0x0000000002cf1fa1: sub (%rax),%r13
  163. 0x0000000002cf1fa4: sub $0x1,%r13d
  164. 0x0000000002cf1fa8: mov 0x8(%rsp,%r13,8),%r13
  165. 0x0000000002cf1fad: test %r13,%r13
  166. 0x0000000002cf1fb0: jne 0x0000000002cf1fbc
  167. 0x0000000002cf1fb2: orq $0x1,0x8(%rax)
  168. 0x0000000002cf1fba: jmp 0x0000000002cf2009
  169. 0x0000000002cf1fbc: mov 0x8(%r13),%r13d
  170. 0x0000000002cf1fc0: shl $0x3,%r13
  171. 0x0000000002cf1fc4: xor 0x8(%rax),%r13
  172. 0x0000000002cf1fc8: test $0xfffffffffffffffc,%r13
  173. 0x0000000002cf1fcf: je 0x0000000002cf2009
  174. 0x0000000002cf1fd1: test $0x2,%r13
  175. 0x0000000002cf1fd8: jne 0x0000000002cf2009
  176. 0x0000000002cf1fda: cmpq $0x0,0x8(%rax)
  177. 0x0000000002cf1fe2: je 0x0000000002cf2005
  178. 0x0000000002cf1fe4: cmpq $0x1,0x8(%rax)
  179. 0x0000000002cf1fec: je 0x0000000002cf2005
  180. 0x0000000002cf1fee: xor 0x8(%rax),%r13
  181. 0x0000000002cf1ff2: test $0xfffffffffffffffc,%r13
  182. 0x0000000002cf1ff9: je 0x0000000002cf2009
  183. 0x0000000002cf1ffb: orq $0x2,0x8(%rax)
  184. 0x0000000002cf2003: jmp 0x0000000002cf2009
  185. 0x0000000002cf2005: mov %r13,0x8(%rax)
  186. 0x0000000002cf2009: add $0x10,%rax
  187. 0x0000000002cf200d: mov -0x28(%rax),%r13
  188. 0x0000000002cf2011: sub $0x4,%r13d
  189. 0x0000000002cf2015: shl $0x3,%r13d
  190. 0x0000000002cf2019: add %r13,%rax
  191. 0x0000000002cf201c: mov %rax,-0x20(%rbp)
  192.  
  193. void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
  194. // set sender sp
  195. lea(r13, Address(rsp, wordSize));
  196. // record last_sp
  197. movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13);
  198. }
  199.  
  200. 0x0000000002cf2020: lea 0x8(%rsp),%r13
  201. 0x0000000002cf2025: mov %r13,-0x10(%rbp)
  202.  
  203. jmp(Address(method, Method::from_interpreted_offset()));
  204. //jump到这里 volatile address _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry
  205.  
  206. 0x0000000002cf2029: jmpq *0x50(%rbx)
  207. 0x0000000002cf202c: nopl 0x0(%rax)
  208. 0x0000000002cf2030: add %al,(%rax)
  209. 0x0000000002cf2032: add %al,(%rax)
  210. 0x0000000002cf2034: add %al,(%rax)
  211. 0x0000000002cf2036: add %al,(%rax)
  212. 0x0000000002cf2038: add %al,(%rax)
  213. 0x0000000002cf203a: add %al,(%rax)
  214. 0x0000000002cf203c: add %al,(%rax)
  215. 0x0000000002cf203e: add %al,(%rax)
  216.  
  217. ----------------------------------------------------------------------

对应的代码为

  1. void TemplateTable::invokespecial(int byte_no) {
  2. transition(vtos, vtos);
  3. assert(byte_no == f1_byte, "use this argument");
  4. prepare_invoke(byte_no, rbx, noreg, // get f1 Method*
  5. rcx); // get receiver also for null check
  6. __ verify_oop(rcx);
  7. __ null_check(rcx);
  8. // do the call
  9. __ profile_call(rax);
  10. __ profile_arguments_type(rax, rbx, r13, false);
  11. __ jump_from_interpreted(rbx, rax);
  12. }
  13. void TemplateTable::prepare_invoke(int byte_no,
  14. Register method, // linked method (or i-klass)
  15. Register index, // itable index, MethodType, etc.
  16. Register recv, // if caller wants to see it
  17. Register flags // if caller wants to test it
  18. ) {
  19. // determine flags
  20. const Bytecodes::Code code = bytecode();
  21. const bool is_invokeinterface = code == Bytecodes::_invokeinterface;
  22. const bool is_invokedynamic = code == Bytecodes::_invokedynamic;
  23. const bool is_invokehandle = code == Bytecodes::_invokehandle;
  24. const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
  25. const bool is_invokespecial = code == Bytecodes::_invokespecial;
  26. const bool load_receiver = (recv != noreg);//true
  27. const bool save_flags = (flags != noreg);//false
  28. assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), "");
  29. assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal");
  30. assert(flags == noreg || flags == rdx, "");
  31. assert(recv == noreg || recv == rcx, "");
  32.  
  33. // setup registers & access constant pool cache\
  34. //recv=rcx,flags=noreg
  35. if (recv == noreg) recv = rcx;//
  36. if (flags == noreg) flags = rdx;
  37. assert_different_registers(method, index, recv, flags);
  38.  
  39. // save 'interpreter return address'
  40. __ save_bcp();
  41.  
  42. load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
  43.  
  44. // maybe push appendix to arguments (just before return address)
  45. if (is_invokedynamic || is_invokehandle) {
  46. Label L_no_push;
  47. __ testl(flags, (1 << ConstantPoolCacheEntry::has_appendix_shift));
  48. __ jcc(Assembler::zero, L_no_push);
  49. // Push the appendix as a trailing parameter.
  50. // This must be done before we get the receiver,
  51. // since the parameter_size includes it.
  52. __ push(rbx);
  53. __ mov(rbx, index);
  54. assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
  55. __ load_resolved_reference_at_index(index, rbx);
  56. __ pop(rbx);
  57. __ push(index); // push appendix (MethodType, CallSite, etc.)
  58. __ bind(L_no_push);
  59. }
  60.  
  61. // load receiver if needed (after appendix is pushed so parameter size is correct)
  62. // Note: no return address pushed yet
  63. if (load_receiver) {//true
  64. __ movl(recv, flags);
  65. __ andl(recv, ConstantPoolCacheEntry::parameter_size_mask);
  66. const int no_return_pc_pushed_yet = -1; // argument slot correction before we push return address
  67. const int receiver_is_at_end = -1; // back off one slot to get receiver
  68. Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end);
  69. __ movptr(recv, recv_addr);
  70. __ verify_oop(recv);
  71. }
  72.  
  73. if (save_flags) {//false
  74. __ movl(r13, flags);
  75. }
  76.  
  77. // compute return type
  78. __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
  79. // Make sure we don't need to mask flags after the above shift
  80. ConstantPoolCacheEntry::verify_tos_state_shift();
  81. // load return address
  82. {
  83. const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);
  84. ExternalAddress table(table_addr);
  85. __ lea(rscratch1, table);
  86. __ movptr(flags, Address(rscratch1, flags, Address::times_ptr));
  87. }
  88.  
  89. // push return address
  90. __ push(flags);
  91.  
  92. // Restore flags value from the constant pool cache, and restore rsi
  93. // for later null checks. r13 is the bytecode pointer
  94. if (save_flags) {
  95. __ movl(flags, r13);
  96. __ restore_bcp();
  97. }
  98. }
  99. //
  100. void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
  101. int bcp_offset,
  102. size_t index_size) {
  103. assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
  104. if (index_size == sizeof(u2)) {
  105. load_unsigned_short(index, Address(r13, bcp_offset));}
  106. //返回
  107. void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
  108. Register index,
  109. int bcp_offset,
  110. size_t index_size) {
  111. assert_different_registers(cache, index);
  112. get_cache_index_at_bcp(index, bcp_offset, index_size); //将index返回值,即为index是bcp的地址的invoke指令的操作数
  113. movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));//将cache放入cache这个变量
  114. assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
  115. // convert from field index to ConstantPoolCacheEntry index
  116. assert(exact_log2(in_words(ConstantPoolCacheEntry::size())) == 2, "else change next line");
  117. shll(index, 2);
  118. }
  119. void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache,
  120. Register index,
  121. Register bytecode,
  122. int byte_no,
  123. int bcp_offset,
  124. size_t index_size) {
  125. get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size);//上边的执行到这里
  126. // We use a 32-bit load here since the layout of 64-bit words on
  127. // little-endian machines allow us that.
  128. //cache 就是constanpoolcache,那么这个操作就是取得方法重写过后的方法所在常量池的序号index
  129. movl(bytecode, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()));
  130. const int shift_count = (1 + byte_no) * BitsPerByte;
  131. assert((byte_no == TemplateTable::f1_byte && shift_count == ConstantPoolCacheEntry::bytecode_1_shift) ||
  132. (byte_no == TemplateTable::f2_byte && shift_count == ConstantPoolCacheEntry::bytecode_2_shift),
  133. "correct shift count");
  134. shrl(bytecode, shift_count);//右移16为
  135. assert(ConstantPoolCacheEntry::bytecode_1_mask == ConstantPoolCacheEntry::bytecode_2_mask, "common mask");
  136. andl(bytecode, ConstantPoolCacheEntry::bytecode_1_mask);
  137. }
  138. -------

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

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

接着节点是

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

就是跳转到了method方法的_from_interpreted_entry

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

  1. void InstanceKlass::link_methods(TRAPS) {
  2. int len = methods()->length();
  3. for (int i = len-1; i >= 0; i--) {
  4. methodHandle m(THREAD, methods()->at(i));
  5.  
  6. // Set up method entry points for compiler and interpreter .
  7. m->link_method(m, CHECK);
  8.  
  9. // This is for JVMTI and unrelated to relocator but the last thing we do
  10. #ifdef ASSERT
  11. if (StressMethodComparator) {
  12. ResourceMark rm(THREAD);
  13. static int nmc = 0;
  14. for (int j = i; j >= 0 && j >= i-4; j--) {
  15. if ((++nmc % 1000) == 0) tty->print_cr("Have run MethodComparator %d times...", nmc);
  16. bool z = MethodComparator::methods_EMCP(m(),
  17. methods()->at(j));
  18. if (j == i && !z) {
  19. tty->print("MethodComparator FAIL: "); m->print(); m->print_codes();
  20. assert(z, "method must compare equal to itself");
  21. }
  22. }
  23. }
  24. #endif //ASSERT
  25. }
  26. }

还有

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

//以上是设置

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

设置

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

设置之前的method内容

  1. 方法的执行过程
  2. enum MethodKind {
  3. zerolocals, // method needs locals initialization
  4. zerolocals_synchronized, // method needs locals initialization & is synchronized
  5. native, // native method
  6. native_synchronized, // native method & is synchronized
  7. empty, // empty method (code: _return)
  8. accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return)
  9. abstract, // abstract method (throws an AbstractMethodException)
  10. method_handle_invoke_FIRST, // java.lang.invoke.MethodHandles::invokeExact, etc.
  11. method_handle_invoke_LAST = (method_handle_invoke_FIRST
  12. + (vmIntrinsics::LAST_MH_SIG_POLY
  13. - vmIntrinsics::FIRST_MH_SIG_POLY)),
  14. java_lang_math_sin, // implementation of java.lang.Math.sin (x)
  15. java_lang_math_cos, // implementation of java.lang.Math.cos (x)
  16. java_lang_math_tan, // implementation of java.lang.Math.tan (x)
  17. java_lang_math_abs, // implementation of java.lang.Math.abs (x)
  18. java_lang_math_sqrt, // implementation of java.lang.Math.sqrt (x)
  19. java_lang_math_log, // implementation of java.lang.Math.log (x)
  20. java_lang_math_log10, // implementation of java.lang.Math.log10 (x)
  21. java_lang_math_pow, // implementation of java.lang.Math.pow (x,y)
  22. java_lang_math_exp, // implementation of java.lang.Math.exp (x)
  23. java_lang_ref_reference_get, // implementation of java.lang.ref.Reference.get()
  24. java_util_zip_CRC32_update, // implementation of java.util.zip.CRC32.update()
  25. java_util_zip_CRC32_updateBytes, // implementation of java.util.zip.CRC32.updateBytes()
  26. java_util_zip_CRC32_updateByteBuffer, // implementation of java.util.zip.CRC32.updateByteBuffer()
  27. number_of_method_entries, //26
  28. invalid = -1
  29. };
  30.  
  31. gdb) p _entry_table
  32. $7 = {0x7f671501e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  33. 0x7f671501f060 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  34. 0x7f6715028d40 "H\213K\020\017\267I*XL\215t\314\370h",
  35. 0x7f671502a620 "H\213K\020\017\267I*XL\215t\314\370h",
  36. 0x7f6715020180 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  37. 0x7f6715020f00 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  38. 0x7f6715021c80 "H\213e\300H\307", <incomplete sequence \360>,
  39. 0x7f6715021c80 "H\213e\300H\307", <incomplete sequence \360>,
  40. 0x7f6715021c80 "H\213e\300H\307", <incomplete sequence \360>,
  41. 0x7f6715021c80 "H\213e\300H\307", <incomplete sequence \360>,
  42. 0x7f6715021c80 "H\213e\300H\307", <incomplete sequence \360>,
  43. 0x7f6715021c80 "H\213e\300H\307", <incomplete sequence \360>,
  44. 0x7f6715021c80 "H\213e\300H\307", <incomplete sequence \360>,
  45. 0x7f6715021f80 "\335D$\b\335\005V\200\232\025\331\301\331\341\337\351\335\300\331\367\017\207\a",
  46. 0x7f6715022300 "\335D$\b\335\005\326|\232\025\331\301\331\341\337\351\335\300\331\367\017\207\a",
  47. 0x7f6715022680 "\335D$\b\335\005Vy\232\025\331\301\331\341\337\351\335\300\331\367\017\207\t",
  48. 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@",
  49. 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@",
  50. 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@",
  51. 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",
  52. 0x7f6715022ee0 "\335D$\b\335D$\030\331\356\337\351\017\207}",
  53. 0x7f6715022b00 "\335D$\b\331\300H\203\354\b\233\331<$\213\004$\201", <incomplete sequence \310>,
  54. 0x7f6715023420 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  55. 0x7f67150241a0 "\201=6C\001\026",
  56. 0x7f6715025ac0 "\201=\026*\001\026",
  57. 0x7f6715027400 "\201=\326\020\001\026"}
  58.  
  59. (gdb) p k
  60. $3 = AbstractInterpreter::zerolocals
  61. (gdb) p/d k
  62. $4 = 0
  63. 三层关系
  64. -------------第一层-----------------
  65. (gdb) p h_method._value
  66. $7 = (Method *) 0x7f2908a13938
  67. (gdb) p * h_method._value
  68. $8 = (Method) {
  69. <Metadata> = {
  70. <MetaspaceObj> = {<No data fields>},
  71. members of Metadata:
  72. _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
  73. _valid = 0
  74. },
  75. members of Method:
  76. _constMethod = 0x7f2908a138c0,
  77. _method_data = 0x0,
  78. _method_counters = 0x0,
  79. _access_flags = {
  80. _flags = 138
  81. },
  82. _vtable_index = -3,
  83. _method_size = 12,
  84. _intrinsic_id = 0 '\000',
  85. _jfr_towrite = 0 '\000',
  86. _caller_sensitive = 0 '\000',
  87. _force_inline = 0 '\000',
  88. _hidden = 0 '\000',
  89. _dont_inline = 0 '\000',
  90. _compiled_invocation_count = 0,
  91. _i2i_entry = 0x0,
  92. _adapter = 0x0,
  93. _from_compiled_entry = 0x0,
  94. _code = 0x0,
  95. _from_interpreted_entry = 0x0,
  96. static extra_stack_entries_for_jsr292 = 1
  97. }
  98. -------------第二层-----------------
  99. (gdb) p *h_method._value._constMethod
  100. $10 = {
  101. <MetaspaceObj> = {<No data fields>},
  102. members of ConstMethod:
  103. _fingerprint = 9223372036854775808,
  104. _constants = 0x7f2908a110e0,
  105. _stackmap_data = 0x0,
  106. _constMethod_size = 15,
  107. _flags = 5,
  108. _code_size = 22,
  109. _name_index = 330,
  110. _signature_index = 331,
  111. _method_idnum = 27,
  112. _max_stack = 2,
  113. _max_locals = 3,
  114. _size_of_parameters = 2,
  115. static MAX_IDNUM = 65534,
  116. static UNSET_IDNUM = 65535
  117. }
  118. -------------第三层-----------------
  119. (gdb) p *h_method._value._constMethod._constants
  120. $9 = (ConstantPool) {
  121. <Metadata> = {
  122. <MetaspaceObj> = {<No data fields>},
  123. members of Metadata:
  124. _vptr.Metadata = 0x7f291fce1070 <vtable for ConstantPool+16>,
  125. _valid = 0
  126. },
  127. members of ConstantPool:
  128. _tags = 0x7f2908a10db0,
  129. _cache = 0x7f2908a14e30,
  130. _pool_holder = 0x100038f38,
  131. _operands = 0x0,
  132. _resolved_references = 0x7f29180e0d60,
  133. _reference_map = 0x7f2908a15dc0,
  134. _flags = 0,
  135. _length = 809,
  136. _saved = {
  137. _resolved_reference_length = 0,
  138. _version = 0
  139. },
  140. _lock = 0x7f29181535c8
  141. }
  142.  
  143. 查看自己写的Test
  144. (gdb) p * m._value
  145. $15 = (Method) {
  146. <Metadata> = {
  147. <MetaspaceObj> = {<No data fields>},
  148. members of Metadata:
  149. _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
  150. _valid = 0
  151. },
  152. members of Method:
  153. _constMethod = 0x7f2908c00588,
  154. _method_data = 0x0,
  155. _method_counters = 0x0,
  156. _access_flags = {
  157. _flags = 9
  158. },
  159. _vtable_index = -3,
  160. _method_size = 12,
  161. _intrinsic_id = 0 '\000',
  162. _jfr_towrite = 0 '\000',
  163. _caller_sensitive = 0 '\000',
  164. _force_inline = 0 '\000',
  165. _hidden = 0 '\000',
  166. _dont_inline = 0 '\000',
  167. _compiled_invocation_count = 0,
  168. _i2i_entry = 0x0,
  169. _adapter = 0x0,
  170. _from_compiled_entry = 0x0,
  171. _code = 0x0,
  172. _from_interpreted_entry = 0x0,
  173. static extra_stack_entries_for_jsr292 = 1
  174. }
  175.  
  176. (gdb) p * m._value._constMethod
  177. $16 = {
  178. <MetaspaceObj> = {<No data fields>},
  179. members of ConstMethod:
  180. _fingerprint = 9223372036854775808,
  181. _constants = 0x7f2908c00080,
  182. _stackmap_data = 0x7f2908c006d8,
  183. _constMethod_size = 30,
  184. _flags = 5,
  185. _code_size = 81,
  186. _name_index = 29,
  187. _signature_index = 30,
  188. _method_idnum = 3,
  189. _max_stack = 4,
  190. _max_locals = 8,
  191. _size_of_parameters = 1,
  192. static MAX_IDNUM = 65534,
  193. static UNSET_IDNUM = 65535
  194. }
  195.  
  196. 这个是_name_index = 29, 29 main方法
  197. (gdb) p k
  198. $18 = AbstractInterpreter::zerolocals
  199. _entry_table[k] =0x7f290901e2e0
  200. set_interpreter_entry(entry);设置;之前
  201. (gdb) p * this
  202. $21 = (Method) {
  203. <Metadata> = {
  204. <MetaspaceObj> = {<No data fields>},
  205. members of Metadata:
  206. _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
  207. _valid = 0
  208. },
  209. members of Method:
  210. _constMethod = 0x7f2908c00588,
  211. _method_data = 0x0,
  212. _method_counters = 0x0,
  213. _access_flags = {
  214. _flags = 9
  215. },
  216. _vtable_index = -3,
  217. _method_size = 12,
  218. _intrinsic_id = 0 '\000',
  219. _jfr_towrite = 0 '\000',
  220. _caller_sensitive = 0 '\000',
  221. _force_inline = 0 '\000',
  222. _hidden = 0 '\000',
  223. _dont_inline = 0 '\000',
  224. _compiled_invocation_count = 0,
  225. _i2i_entry = 0x0,
  226. _adapter = 0x0,
  227. _from_compiled_entry = 0x0,
  228. _code = 0x0,
  229. _from_interpreted_entry = 0x0,
  230. static extra_stack_entries_for_jsr292 = 1
  231. }
  232. 设置之后
  233. (gdb) p * this
  234. $23 = (Method) {
  235. <Metadata> = {
  236. <MetaspaceObj> = {<No data fields>},
  237. members of Metadata:
  238. _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
  239. _valid = 0
  240. },
  241. members of Method:
  242. _constMethod = 0x7f2908c00588,
  243. _method_data = 0x0,
  244. _method_counters = 0x0,
  245. _access_flags = {
  246. _flags = 9
  247. },
  248. _vtable_index = -3,
  249. _method_size = 12,
  250. _intrinsic_id = 0 '\000',
  251. _jfr_towrite = 0 '\000',
  252. _caller_sensitive = 0 '\000',
  253. _force_inline = 0 '\000',
  254. _hidden = 0 '\000',
  255. _dont_inline = 0 '\000',
  256. _compiled_invocation_count = 0,
  257. _i2i_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001", //设置了这个
  258. _adapter = 0x0,
  259. _from_compiled_entry = 0x0,
  260. _code = 0x0,
  261. _from_interpreted_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",//设置了这个
  262. static extra_stack_entries_for_jsr292 = 1
  263. }
  264.  
  265. address Method::make_adapters(methodHandle mh, TRAPS) {
  266. // Adapters for compiled code are made eagerly here. They are fairly
  267. // small (generally < 100 bytes) and quick to make (and cached and shared)
  268. // so making them eagerly shouldn't be too expensive.
  269. AdapterHandlerEntry* adapter = AdapterHandlerLibrary::get_adapter(mh);
  270. if (adapter == NULL ) {
  271. THROW_MSG_NULL(vmSymbols::java_lang_VirtualMachineError(), "out of space in CodeCache for adapters");
  272. }
  273.  
  274. mh->set_adapter_entry(adapter);
  275. mh->_from_compiled_entry = adapter->get_c2i_entry();
  276. return adapter->get_c2i_entry();
  277. }
  278.  
  279. 查看adapter
  280. $31 = (AdapterHandlerEntry *) 0x7f29180aee10
  281. (gdb) x/8xg adapter
  282. 0x7f29180aee10: 0xf1f1f1f1f1f1f1f1 0xf1f1f1f1b0000000
  283. 0x7f29180aee20: 0x0000000000000000 0x00007f2918087c98 //第一个成员变量_fingerprint
  284. 0x7f29180aee30: 0x00007f2909106ae0 0x00007f2909106bf4 c2i
  285. 0x7f29180aee40: 0x00007f2909106bc7 0x0000000000000000
  286.  
  287. (gdb) p mh->_from_compiled_entry
  288. $30 = (volatile address) 0x7f2909106bf4 "H\201{P"
  289.  
  290. (gdb) x/120i 0x00007f2909106ae0
  291. 0x7f2909106ae0: mov (%rsp),%rax
  292. 0x7f2909106ae4: movabs $0x7f29090053e0,%r11
  293. 0x7f2909106aee: cmp %r11,%rax
  294. 0x7f2909106af1: jbe 0x7f2909106b0a
  295. 0x7f2909106af7: movabs $0x7f29091053e0,%r11
  296. 0x7f2909106b01: cmp %r11,%rax
  297. 0x7f2909106b04: jb 0x7f2909106ba7
  298. 0x7f2909106b0a: movabs $0x7f2909000420,%r11
  299. 0x7f2909106b14: cmp %r11,%rax
  300. 0x7f2909106b17: jbe 0x7f2909106b30
  301. 0x7f2909106b1d: movabs $0x7f2909004e58,%r11
  302. 0x7f2909106b27: cmp %r11,%rax
  303. 0x7f2909106b2a: jb 0x7f2909106ba7
  304. 0x7f2909106b30: mov %rsp,-0x28(%rsp)
  305. 0x7f2909106b35: sub $0x80,%rsp
  306. 0x7f2909106b3c: mov %rax,0x78(%rsp)
  307. 0x7f2909106b41: mov %rcx,0x70(%rsp)
  308. 0x7f2909106b46: mov %rdx,0x68(%rsp)
  309. 0x7f2909106b4b: mov %rbx,0x60(%rsp)
  310. 0x7f2909106b50: mov %rbp,0x50(%rsp)
  311. 0x7f2909106b55: mov %rsi,0x48(%rsp)
  312. 0x7f2909106b5a: mov %rdi,0x40(%rsp)
  313. 0x7f2909106b5f: mov %r8,0x38(%rsp)
  314. 0x7f2909106b64: mov %r9,0x30(%rsp)
  315. 0x7f2909106b69: mov %r10,0x28(%rsp)
  316. 0x7f2909106b6e: mov %r11,0x20(%rsp)
  317. 0x7f2909106b73: mov %r12,0x18(%rsp)
  318. 0x7f2909106b78: mov %r13,0x10(%rsp)
  319. 0x7f2909106b7d: mov %r14,0x8(%rsp)
  320. 0x7f2909106b82: mov %r15,(%rsp)
  321. 0x7f2909106b86: movabs $0x7f291f7bd600,%rdi
  322. 0x7f2909106b90: movabs $0x7f2909106b30,%rsi
  323. 0x7f2909106b9a: mov %rsp,%rdx
  324. 0x7f2909106b9d: and $0xfffffffffffffff0,%rsp
  325. 0x7f2909106ba1: callq 0x7f291f238dc8 <MacroAssembler::debug64(char*, long, long*)>
  326. 0x7f2909106ba6: hlt
  327. 0x7f2909106ba7: mov %rsp,%r11
  328. 0x7f2909106baa: and $0xfffffffffffffff0,%rsp
  329. 0x7f2909106bae: push %rax
  330. 0x7f2909106baf: mov %r11,%rax
  331. 0x7f2909106bb2: mov 0x48(%rbx),%r11
  332. 0x7f2909106bb6: mov 0x8(%rax),%rsi
  333. 0x7f2909106bba: mov %rbx,0x248(%r15)
  334. 0x7f2909106bc1: mov %rbx,%rax
  335. 0x7f2909106bc4: jmpq *%r11
  336. 0x7f2909106bc7: mov 0x8(%rsi),%ebx
  337. 0x7f2909106bca: shl $0x3,%rbx
  338. 0x7f2909106bce: cmp 0x10(%rax),%rbx
  339. 0x7f2909106bd2: mov 0x8(%rax),%rbx
  340. 0x7f2909106bd6: je 0x7f2909106be1
  341. 0x7f2909106bdc: jmpq 0x7f2909105be0
  342. 0x7f2909106be1: cmpq $0x0,0x50(%rbx)
  343. 0x7f2909106be9: je 0x7f2909106ce4
  344. 0x7f2909106bef: jmpq 0x7f2909105be0
  345. 0x7f2909106bf4: cmpq $0x0,0x50(%rbx)
  346. 0x7f2909106bfc: je 0x7f2909106ce4
  347. 0x7f2909106c02: mov %rsp,%r13
  348. 0x7f2909106c05: mov (%rsp),%rax
  349. 0x7f2909106c09: and $0xfffffffffffffff0,%rsp
  350. 0x7f2909106c0d: pushfq
  351. 0x7f2909106c0e: sub $0x8,%rsp
  352. 0x7f2909106c12: mov %rsp,-0x28(%rsp)
  353. 0x7f2909106c17: sub $0x80,%rsp
  354. 0x7f2909106c1e: mov %rax,0x78(%rsp)
  355. 0x7f2909106c23: mov %rcx,0x70(%rsp)
  356. 0x7f2909106c28: mov %rdx,0x68(%rsp)
  357. 0x7f2909106c2d: mov %rbx,0x60(%rsp)
  358. 0x7f2909106c32: mov %rbp,0x50(%rsp)
  359. 0x7f2909106c37: mov %rsi,0x48(%rsp)
  360. 0x7f2909106c3c: mov %rdi,0x40(%rsp)
  361. 0x7f2909106c41: mov %r8,0x38(%rsp)
  362. 0x7f2909106c46: mov %r9,0x30(%rsp)
  363. 0x7f2909106c4b: mov %r10,0x28(%rsp)
  364. 0x7f2909106c50: mov %r11,0x20(%rsp)
  365. 0x7f2909106c55: mov %r12,0x18(%rsp)
  366. 0x7f2909106c5a: mov %r13,0x10(%rsp)
  367. 0x7f2909106c5f: mov %r14,0x8(%rsp)
  368. 0x7f2909106c64: mov %r15,(%rsp)
  369. 0x7f2909106c68: sub $0x200,%rsp
  370. 0x7f2909106c6f: fxsave64 (%rsp)
  371. 0x7f2909106c74: mov %rbx,%rdi
  372. 0x7f2909106c77: mov %rax,%rsi
  373. 0x7f2909106c7a: callq 0x7f291f3d3a32 <SharedRuntime::fixup_callers_callsite(Method*, unsigned char*)>
  374. 0x7f2909106c7f: fxrstor64 (%rsp)
  375. 0x7f2909106c84: add $0x200,%rsp
  376. 0x7f2909106c8b: mov (%rsp),%r15
  377. 0x7f2909106c8f: mov 0x8(%rsp),%r14
  378. 0x7f2909106c94: mov 0x10(%rsp),%r13
  379. 0x7f2909106c99: mov 0x18(%rsp),%r12
  380. 0x7f2909106c9e: mov 0x20(%rsp),%r11
  381. 0x7f2909106ca3: mov 0x28(%rsp),%r10
  382. 0x7f2909106ca8: mov 0x30(%rsp),%r9
  383. 0x7f2909106cad: mov 0x38(%rsp),%r8
  384. 0x7f2909106cb2: mov 0x40(%rsp),%rdi
  385. 0x7f2909106cb7: mov 0x48(%rsp),%rsi
  386. 0x7f2909106cbc: mov 0x50(%rsp),%rbp
  387. 0x7f2909106cc1: mov 0x60(%rsp),%rbx
  388. 0x7f2909106cc6: mov 0x68(%rsp),%rdx
  389. 0x7f2909106ccb: mov 0x70(%rsp),%rcx
  390. 0x7f2909106cd0: mov 0x78(%rsp),%rax
  391. 0x7f2909106cd5: add $0x80,%rsp
  392. 0x7f2909106cdc: add $0x8,%rsp
  393. 0x7f2909106ce0: popfq
  394. 0x7f2909106ce1: mov %r13,%rsp
  395. 0x7f2909106ce4: pop %rax
  396. 0x7f2909106ce5: mov %rsp,%r13
  397. 0x7f2909106ce8: sub $0x10,%rsp
  398. 0x7f2909106cec: mov %rax,(%rsp)
  399. 0x7f2909106cf0: mov %rsi,0x8(%rsp)
  400. 0x7f2909106cf5: mov 0x38(%rbx),%rcx
  401. 0x7f2909106cf9: jmpq *%rcx
  402. 0x7f2909106cfb: hlt
  403. 0x7f2909106cfc: hlt
  404. 0x7f2909106cfd: hlt
  405. 0x7f2909106cfe: hlt
  406. 0x7f2909106cff: hlt
  407. 0x7f2909106d00: or %al,(%rax)
  408. 0x7f2909106d02: add %al,(%rax)
  409. 0x7f2909106d04: add %al,(%rax)
  410. 0x7f2909106d06: add %al,(%rax)
  411.  
  412. 这个上面已经分析过了,这里省略了...
  413. 设置完成了i2i
  414. (gdb) p m._value
  415. $33 = (Method *) 0x7f2908c00678
  416. (gdb) p * m._value
  417. $34 = (Method) {
  418. <Metadata> = {
  419. <MetaspaceObj> = {<No data fields>},
  420. members of Metadata:
  421. _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
  422. _valid = 0
  423. },
  424. members of Method:
  425. _constMethod = 0x7f2908c00588,
  426. _method_data = 0x0,
  427. _method_counters = 0x0,
  428. _access_flags = {
  429. _flags = 9
  430. },
  431. _vtable_index = -3,
  432. _method_size = 12,
  433. _intrinsic_id = 0 '\000',
  434. _jfr_towrite = 0 '\000',
  435. _caller_sensitive = 0 '\000',
  436. _force_inline = 0 '\000',
  437. _hidden = 0 '\000',
  438. _dont_inline = 0 '\000',
  439. _compiled_invocation_count = 0,
  440. _i2i_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  441. _adapter = 0x7f29180aee10,
  442. _from_compiled_entry = 0x7f2909106bf4 "H\201{P", //就是这里设置了compiled_entry取值是从adapter中拿到的
  443.  
  444. _code = 0x0,
  445. _from_interpreted_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  446. static extra_stack_entries_for_jsr292 = 1
  447. }
  448.  
  449. 循环第2
  450. (gdb) p * m._value._constMethod
  451. $35 = {
  452. <MetaspaceObj> = {<No data fields>},
  453. members of ConstMethod:
  454. _fingerprint = 9223372036854775808,
  455. _constants = 0x7f2908c00080,
  456. _stackmap_data = 0x0,
  457. _constMethod_size = 7,
  458. _flags = 1,
  459. _code_size = 6,
  460. _name_index = 10,
  461. _signature_index = 11,
  462. _method_idnum = 2,
  463. _max_stack = 1,
  464. _max_locals = 0,
  465. _size_of_parameters = 0,
  466. static MAX_IDNUM = 65534,
  467. static UNSET_IDNUM = 65535
  468. }
  469. 查看_name_index = 10, 知道是clint方法
  470. 设置之前
  471. (gdb) p this
  472. $37 = (Method * const) 0x7f2908c003b0
  473. (gdb) p * this
  474. $38 = (Method) {
  475. <Metadata> = {
  476. <MetaspaceObj> = {<No data fields>},
  477. members of Metadata:
  478. _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
  479. _valid = 0
  480. },
  481. members of Method:
  482. _constMethod = 0x7f2908c00378,
  483. _method_data = 0x0,
  484. _method_counters = 0x0,
  485. _access_flags = {
  486. _flags = 8
  487. },
  488. _vtable_index = -3,
  489. _method_size = 12,
  490. _intrinsic_id = 0 '\000',
  491. _jfr_towrite = 0 '\000',
  492. _caller_sensitive = 0 '\000',
  493. _force_inline = 0 '\000',
  494. _hidden = 0 '\000',
  495. _dont_inline = 0 '\000',
  496. _compiled_invocation_count = 0,
  497. _i2i_entry = 0x0,
  498. _adapter = 0x0,
  499. _from_compiled_entry = 0x0,
  500. _code = 0x0,
  501. _from_interpreted_entry = 0x0,
  502. static extra_stack_entries_for_jsr292 = 1
  503. }
  504.  
  505. 3个循环
  506. (gdb) p * this
  507. $40 = (Method) {
  508. <Metadata> = {
  509. <MetaspaceObj> = {<No data fields>},
  510. members of Metadata:
  511. _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
  512. _valid = 0
  513. },
  514. members of Method:
  515. _constMethod = 0x7f2908c00410,
  516. _method_data = 0x0,
  517. _method_counters = 0x0,
  518. _access_flags = {
  519. _flags = 1
  520. },
  521. _vtable_index = -3,
  522. _method_size = 12,
  523. _intrinsic_id = 0 '\000',
  524. _jfr_towrite = 0 '\000',
  525. _caller_sensitive = 0 '\000',
  526. _force_inline = 0 '\000',
  527. _hidden = 0 '\000',
  528. _dont_inline = 0 '\000',
  529. _compiled_invocation_count = 0,
  530. _i2i_entry = 0x0,
  531. _adapter = 0x0,
  532. _from_compiled_entry = 0x0,
  533. _code = 0x0,
  534. _from_interpreted_entry = 0x0,
  535. static extra_stack_entries_for_jsr292 = 1
  536. }
  537. (gdb) p * this._constMethod
  538. $41 = {
  539. <MetaspaceObj> = {<No data fields>},
  540. members of ConstMethod:
  541. _fingerprint = 9223372036854775808,
  542. _constants = 0x7f2908c00080,
  543. _stackmap_data = 0x0,
  544. _constMethod_size = 14,
  545. _flags = 5,
  546. _code_size = 15,
  547. _name_index = 17,
  548. _signature_index = 18,
  549. _method_idnum = 1,
  550. _max_stack = 2,
  551. _max_locals = 3,
  552. _size_of_parameters = 3,
  553. static MAX_IDNUM = 65534,
  554. static UNSET_IDNUM = 65535
  555. }
  556.  
  557. _name_index = 17, 查看常量池是init方法
  558. 设置之后
  559. $46 = (Method *) 0x7f2908c00480
  560. (gdb) p * mh._value
  561. $47 = (Method) {
  562. <Metadata> = {
  563. <MetaspaceObj> = {<No data fields>},
  564. members of Metadata:
  565. _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
  566. _valid = 0
  567. },
  568. members of Method:
  569. _constMethod = 0x7f2908c00410,
  570. _method_data = 0x0,
  571. _method_counters = 0x0,
  572. _access_flags = {
  573. _flags = 1
  574. },
  575. _vtable_index = -3,
  576. _method_size = 12,
  577. _intrinsic_id = 0 '\000',
  578. _jfr_towrite = 0 '\000',
  579. _caller_sensitive = 0 '\000',
  580. _force_inline = 0 '\000',
  581. _hidden = 0 '\000',
  582. _dont_inline = 0 '\000',
  583. _compiled_invocation_count = 0,
  584. _i2i_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  585. _adapter = 0x7f29180b0048, //这个每个方法都不一样的
  586. _from_compiled_entry = 0x7f2909125a21 "H\201{P",
  587. _code = 0x0,
  588. _from_interpreted_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  589. static extra_stack_entries_for_jsr292 = 1
  590. }
  591.  
  592. 4个循环
  593. (gdb) p * this
  594. $52 = (Method) {
  595. <Metadata> = {
  596. <MetaspaceObj> = {<No data fields>},
  597. members of Metadata:
  598. _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
  599. _valid = 0
  600. },
  601. members of Method:
  602. _constMethod = 0x7f2908c004e0,
  603. _method_data = 0x0,
  604. _method_counters = 0x0,
  605. _access_flags = {
  606. _flags = 1
  607. },
  608. _vtable_index = -3,
  609. _method_size = 12,
  610. _intrinsic_id = 0 '\000',
  611. _jfr_towrite = 0 '\000',
  612. _caller_sensitive = 0 '\000',
  613. _force_inline = 0 '\000',
  614. _hidden = 0 '\000',
  615. _dont_inline = 0 '\000',
  616. _compiled_invocation_count = 0,
  617. _i2i_entry = 0x0,
  618. _adapter = 0x0,
  619. _from_compiled_entry = 0x0,
  620. _code = 0x0,
  621. _from_interpreted_entry = 0x0,
  622. static extra_stack_entries_for_jsr292 = 1
  623. }
  624.  
  625. 执行之后
  626. (gdb) p *m._value
  627. $55 = (Method) {
  628. <Metadata> = {
  629. <MetaspaceObj> = {<No data fields>},
  630. members of Metadata:
  631. _vptr.Metadata = 0x7f291fcf1b90 <vtable for Method+16>,
  632. _valid = 0
  633. },
  634. members of Method:
  635. _constMethod = 0x7f2908c004e0,
  636. _method_data = 0x0,
  637. _method_counters = 0x0,
  638. _access_flags = {
  639. _flags = 1
  640. },
  641. _vtable_index = -3,
  642. _method_size = 12,
  643. _intrinsic_id = 0 '\000',
  644. _jfr_towrite = 0 '\000',
  645. _caller_sensitive = 0 '\000',
  646. _force_inline = 0 '\000',
  647. _hidden = 0 '\000',
  648. _dont_inline = 0 '\000',
  649. _compiled_invocation_count = 0,
  650. _i2i_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  651. _adapter = 0x7f29180aee10,//这个值不同呢
  652.  
  653. _from_compiled_entry = 0x7f2909106bf4 "H\201{P",
  654. _code = 0x0,
  655. _from_interpreted_entry = 0x7f290901e2e0 "H\213S\020\017\267J*\017\267R(+с\372\366\001",
  656. static extra_stack_entries_for_jsr292 = 1
  657. }

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

jvm源码解读--12 invokspecial指令的解读的更多相关文章

  1. JVM源码分析之javaagent原理完全解读

    概述 本文重点讲述javaagent的具体实现,因为它面向的是我们Java程序员,而且agent都是用Java编写的,不需要太多的C/C++编程基础,不过这篇文章里也会讲到JVMTIAgent(C实现 ...

  2. JVM源码分析之javaagent原理完全解读--转

    原文地址:http://www.infoq.com/cn/articles/javaagent-illustrated 概述 本文重点讲述javaagent的具体实现,因为它面向的是我们Java程序员 ...

  3. JVM 源码分析之 javaagent 原理完全解读

    转载:https://infoq.cn/article/javaagent-illustrated 本文重点讲述 javaagent 的具体实现,因为它面向的是我们 Java 程序员,而且 agent ...

  4. JVM源码分析之SystemGC完全解读

    JVM源码分析之SystemGC完全解读 概述 JVM的GC一般情况下是JVM本身根据一定的条件触发的,不过我们还是可以做一些人为的触发,比如通过jvmti做强制GC,通过System.gc触发,还可 ...

  5. JVM源码分析之堆外内存完全解读

    JVM源码分析之堆外内存完全解读   寒泉子 2016-01-15 17:26:16 浏览6837 评论0 阿里技术协会 摘要: 概述 广义的堆外内存 说到堆外内存,那大家肯定想到堆内内存,这也是我们 ...

  6. JVM 源码解读之 CMS 何时会进行 Full GC

    t点击上方"涤生的博客",关注我 转载请注明原创出处,谢谢!如果读完觉得有收获的话,欢迎点赞加关注. 前言 本文内容是基于 JDK 8 在文章 JVM 源码解读之 CMS GC 触 ...

  7. jvm源码解读--17 Java的wait()、notify()学习

    write and debug by 张艳涛 wait()和notify()的通常用法 A线程取得锁,执行wait(),释放锁; B线程取得锁,完成业务后执行notify(),再释放锁; B线程释放锁 ...

  8. 从jvm源码看synchronized

    从jvm源码看synchronized 索引 synchronized的使用 修饰实例方法 修饰静态方法 修饰代码块 总结 Synchronzied的底层原理 对象头和内置锁(ObjectMonito ...

  9. JVM源码分析-类加载场景实例分析

    A类调用B类的静态方法,除了加载B类,但是B类的一个未被调用的方法间接使用到的C类却也被加载了,这个有意思的场景来自一个提问:方法中使用的类型为何在未调用时尝试加载?. 场景如下: public cl ...

随机推荐

  1. FlinkSQL写入Kafka/ES/MySQL示例-JAVA

    一.背景说明 Flink的API做了4层的封装,上两层TableAPI.SQL语法相对简单便于编写,面对小需求可以快速上手解决,本文参考官网及部分线上教程编写source端.sink端代码,分别读取s ...

  2. SpringBoot2配置文件application.yaml

    源码基于SpringBoot 2.4.4 1.认识配置文件 1.1 配置文件的加载 创建SpringBoot项目的时候,会自动创建一个application.properties文件,该文件是Spri ...

  3. OO unit2 summary

    Unit2 一.第一次作业 1.UML 2.Sequence Diagram 3.同步块设置与锁处理 采用了生产者-消费者模式,用共享对象来连接不同的线程. 第一次作业中,我有三个线程:Receive ...

  4. RobotFramework + Python 自动化入门 四 (Web进阶)

    在<RobotFramwork + Python 自动化入门 一>中,完成了一个Robot环境搭建及测试脚本的创建和执行. 在<RobotFramwork + Python 自动化入 ...

  5. 安装linux 报错(initramfs) Unable to find a medium containing a live file system

    如题,linux 安装报错:(initramfs) Unable to find a medium containing a live file system 我是用UItraISO做的启动盘遇到这个 ...

  6. 在vue中下拉框切换事件中改新建表单中的一个值,页面不显示

    事件中改新建表单中的一个值,页面不显示,当另一个对象值发生改变时,这个页面上的值才会显示 由于新建表单是弹窗,在弹出时会重新给每个字段重新赋值,在赋值时没给这个字段赋值(常见新加功能时,加了一个字段, ...

  7. gomod使用小结

    gomod使用小结 使用方法 把工程拷贝到$GOPATH/src之外 在工程目录下执行:go mod init {module name}该命令会创建一个go.mod文件 然后在该目录下执行 go b ...

  8. PL/SQL插入数据报错:Access violation at address 00413A81 in module 'plsqldev.exe'. Read of address 00000000

    前言 今天同事在使用plsql给oracl数据库插入记录时报错:Access violation at address 00413A81 in module 'plsqldev.exe'. Read ...

  9. hdu5438 拓扑排序+DFS

    解析 对一个有向无环图(Directed Acyclic Graph,简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则 ...

  10. 什么是DDoS黑洞路由?

    1. 什么是DDoS黑洞路由? DDoS黑洞路由/过滤(有时称为黑孔)是缓解DDoS攻击的一种对策,网络流量将被路由到"黑洞"中并且丢失.如果在没有特定限制条件下实施黑洞过滤,合法 ...