转载

Java Main 如何是如何被执行的?

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方法:

  1. // do call  
  2.   { JavaCallWrapper link(method, receiver, result, CHECK); 
  3.     { HandleMark hm(thread);   // HandleMark used by HandleMarkCleaner  
  4.  
  5.       StubRoutines::call_stub()( 
  6.         (address)&link, 
  7.          // (intptr_t*)&(result->_value), // see NOTE above (compiler problem)  
  8.         result_val_address,           // see NOTE above (compiler problem)  
  9.         result_type, 
  10.         method(), 
  11.         entry_point, 
  12.         args->parameters(), 
  13.         args->size_of_parameters(), 
  14.         CHECK 
  15.       ); 
  16.  
  17.       result = link.result();    
  18.        // Preserve oop return value across possible gc points  
  19.        if  (oop_result_flag) { 
  20.         thread->set_vm_result((oop) result->get_jobject()); 
  21.       } 
  22.     } 
  23.   } 

call_stub()定义在/hotspot/src/share/vm/runtime/stubRoutines.h中,实际上返回的就 是CallStub函数指针_call_stub_entry,该指针指向call_stub的汇编实现的目标代码指令地址,即call_stub的例程 入口。

  1. // Calls to Java  
  2.   typedef  void  (*CallStub)( 
  3.     address   link, 
  4.     intptr_t* result, 
  5.     BasicType result_type, 
  6.     methodOopDesc* method, 
  7.     address   entry_point, 
  8.     intptr_t* parameters, 
  9.      int        size_of_parameters, 
  10.     TRAPS 
  11.   ); 
  12.    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 位操作,下表描述了各寄存器的命名和作用

Java Main 如何是如何被执行的?

此外,还有16个128位的XMM寄存器,分别为xmm0-15,x84-64的寄存器遵循调用约定(Calling Conventions):

https://msdn.microsoft.com/en-US/library/zthk2dkh(v=vs.80).aspx

正文到此结束
Loading...