Java Main 如何是如何被执行的?(1)
Java Main 如何是如何被执行的?(1)
java应用程序的启动在在/hotspot/src/share/tools/launcher/java.c的main()函数中,而在虚拟机 初始化过程中,将创建并启动Java的Main线程。最后将调用JNIEnv的CallStaticVoidMethod()来执行main方法。
CallStaticVoidMethod()对应的jni函数为jni_CallStaticVoidMethod,定义在/hotspot /src/share/vm/prims/jni.cpp中,而jni_CallStaticVoidMethod()又调用了 jni_invoke_static(),jni_invoke_static()通过JavaCalls的call()发起对Java方法的调用
所有来自虚拟机对Java函数的调用最终都将由JavaCalls模块来完成,JavaCalls将通过call_helper()来执行Java方法并返回调用结果,并最终调用StubRoutines::call_stub()来执行Java方法:
- // do call
- { 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());
- }
- }
- }
call_stub()定义在/hotspot/src/share/vm/runtime/stubRoutines.h中,实际上返回的就 是CallStub函数指针_call_stub_entry,该指针指向call_stub的汇编实现的目标代码指令地址,即call_stub的例程 入口。
- // Calls to Java
- typedef void (*CallStub)(
- address link,
- intptr_t* result,
- BasicType result_type,
- methodOopDesc* method,
- address entry_point,
- intptr_t* parameters,
- int size_of_parameters,
- TRAPS
- );
- static CallStub call_stub() { return CAST_TO_FN_PTR(CallStub, _call_stub_entry); }
在分析call_stub的汇编代码之前,先了解下x86寄存器和栈帧以及函数调用的相关知识。
x86-64的所有寄存器都是与 机器字长(数据总线位宽)相同,即64位的,x86-64将x86的8个32位通用寄存器扩展为64位(eax、ebx、ecx、edx、eci、 edi、ebp、esp),并且增加了8个新的64位寄存器(r8-r15),在命名方式上,也从”exx”变为”rxx”,但仍保留”exx”进行32 位操作,下表描述了各寄存器的命名和作用
此外,还有16个128位的XMM寄存器,分别为xmm0-15,x84-64的寄存器遵循调用约定(Calling Conventions):
https://msdn.microsoft.com/en-US/library/zthk2dkh(v=vs.80).aspx

用户点评