[inside hotspot] java方法调用的StubCode

[inside hotspot] java方法调用的StubCode

众所周知jvm有invokestatic,invokedynamic,invokestatic,invokespecial,invokevirtual几条方法调用指令,每个负责调用不同的方法,
而这些方法调用落实到hotspot上都位于hotspot\src\share\vm\runtime\javaCalls.hpp的JavaCalls :

1. JavaCalls class JavaCalls: AllStatic { static void call_helper(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS); public: // call_special // ------------ // The receiver must be first oop in argument list static void call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS); static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); // No args static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS); static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS); // virtual call // ------------ // The receiver must be first oop in argument list static void call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS); static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, TRAPS); // No args static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS); static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS); // Static call // ----------- static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS); static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS); static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS); static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, Handle arg3, TRAPS); // Low-level interface static void call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS); };

上面的方法是自解释的,对应各自的invoke*指令,这些call_static,call_virtual内部调用了call()函数:

void JavaCalls::call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) { assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls"); os::os_exception_wrapper(call_helper, result, method, args, THREAD); }

call()只是简单检查了一下线程信息,以及根据平台比如windows会使用结构化异常(SEH)包裹call_helper,最终执行方法调用的还是call_helper。

void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) { ... // 如果当前方法为空,则直接返回 if (method->is_empty_method()) { assert(result->get_type() == T_VOID, "an empty method must return a void value"); return; } ... //根据情况决定是否编译该方法,JIT和-Xcomp都有可能触发它 CompilationPolicy::compile_if_required(method, CHECK); // 解释器入口点 address entry_point = method->from_interpreted_entry(); if (JvmtiExport::can_post_interpreter_events() && thread->is_interp_only_mode()) { entry_point = method->interpreter_entry(); } // 确定返回值类型 BasicType result_type = runtime_type_from(result); bool oop_result_flag = (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY); // 返回值地址 intptr_t* result_val_address = (intptr_t*)(result->get_value_addr()); // 确定receiver,如果是static函数就没有receiver Handle receiver = (!method->is_static()) ? args->receiver() : Handle(); if (!thread->stack_guards_enabled()) { thread->reguard_stack(); } // 确认当前sp是否到达ShadowPages,即是否会触发栈溢出错误 address sp = os::current_stack_pointer(); if (!os::stack_shadow_pages_available(THREAD, method, sp)) { // Throw stack overflow exception with preinitialized exception. Exceptions::throw_stack_overflow_exception(THREAD, __FILE__, __LINE__, method); return; } else { // Touch pages checked if the OS needs them to be touched to be mapped. os::map_stack_shadow_pages(sp); } // 执行调用 { JavaCallWrapper link(method, receiver, result, CHECK); { HandleMark hm(thread); // HandleMark used by HandleMarkCleaner StubRoutines::call_stub()( (address)&link, // (intptr_t*)&(result->_value), // see NOTE above (compiler problem) result_val_address, // see NOTE above (compiler problem) result_type, method(), entry_point, args->parameters(), args->size_of_parameters(), CHECK ); result = link.result(); // circumvent MS C++ 5.0 compiler bug (result is clobbered across call) // Preserve oop return value across possible gc points if (oop_result_flag) { thread->set_vm_result((oop) result->get_jobject()); } } } // 设置返回值 if (oop_result_flag) { result->set_jobject((jobject)thread->vm_result()); thread->set_vm_result(NULL); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjgfg.html