Hotspot主要有两种解释器,而下面我们主要讨论的是 Template Intepreter也叫asm interprete解释器, 文章下面的介绍基本都是基于template解释器
我们举一个invokespecial的例子,下面是templateTable方法解释invokespecial的代码
void TemplateTable::invokespecial(int byte_no) { transition(vtos, vtos); assert(byte_no == f1_byte, "use this argument"); prepare_invoke(rbx, noreg, byte_no); // do the call __ verify_oop(rbx); __ profile_call(rax); __ jump_from_interpreted(rbx, rax); }
函数prepare_invoke的层级调用关系
TemplateTable::prepare_invoke
-> TemplateTable::load_invoke_cp_cache_entry
-> TemplateTable::resolve_cache_and_index
在函数中resolve_cache_and_index可以看到
1. 首先先检查constantpoolcache,是否将方法指针保存到到线程的constantpoolcache里,如果有在方法里会使用jcc跳转到Label resolved去,而Lable resolved 在方法第一次运行结束后bind到函数的末尾。
2. 如果cache里没有那么会尝试用interpreterRuntime:resolve_invoke去找到正确的method, 并保存到constant pool cache 里
case Bytecodes::_invokevirtual: case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { prepare_to_jump_from_interpreted(); if (JvmtiExport::can_post_interpreter_events()) { Label run_compiled_code; // JVMTI events, such as single-stepping, are implemented partly by avoiding running // compiled code in threads for which the event is enabled. Check here for // interp_only_mode if these events CAN be enabled. get_thread(temp); // interp_only is an int, on little endian it is sufficient to test the byte only // Is a cmpl faster (ce cmpb(Address(temp, JavaThread::interp_only_mode_offset()), 0); jcc(Assembler::zero, run_compiled_code); jmp(Address(method, methodOopDesc::interpreter_entry_offset())); bind(run_compiled_code); } jmp(Address(method, methodOopDesc::from_interpreted_offset())); }我们看到跳转到了methodoop中的_from_interpreted_entry,也就是在前面的博客里(java JNI (四) 初始化JNI方法)说的generate_native_entry 中