main函数在openjdk\jdk\src\share\bin\main.c文件中。简单流程分析如下:
main->JLI_Launch
1.SelectVersion->LocateJRE,定位jre的位置。因为不同的操作系统上定位jre的方式不同,相关代码就和平台相关了,windows相关的一些代码在openjdk\jdk\src\windows下,而linux和solaris相关代码在openjdk\jdk\src\solaris下。这部分调用到的代码都在{os}\bin\java_md.c中。简单的说,windows中,LocateJRE要通过查找注册表来定位jre的位置,而Linux下可能需要读取环境变量等等,暂时不深入分析。
2.CreateExecutionEnvironment->GetJVMPath 得到jvm的路径,其实就是找到相应的动态链接库,具体到linux上,就是libjvm.so文件。
3.LoadJavaVM,Linux上是加载libjvm.so,windows上是加载jvm.dll,导出JNI_CreateJavaVM,JNI_GetDefaultJavaVMInitArgs等函数。
4.获取classpath。
5.ContinueInNewThread(&ifn, argc, argv, jarfile, classname, ret);在一个新线程中启动jvm。
ContinueInNewThreadd的功能是,调用GetDefaultJavaVMInitArgs(其实是调用JNI_GetDefaultJavaVMInitArgs)获取虚拟机初始化参数,设定线程栈的大小,创建java程序需要的各项参数。然后调用下面函数
ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args);
因为不同操作系统创建线程的方式不同,所以又进入os相关的代码,{os}\bin\java_md.c中的
int ContinueInNewThread0(int (JNICALL *continuation)(void *), jlong stack_size, void * args)函数。
阅读其代码,可知Linux上是通过pthread_create创建线程,Solaris通过thr_create创建线程,而windows则通过_beginthreadex创建线程。
在新线程中调用JavaMain 函数,即
openjdk\jdk\src\share\bin\main.c中的
int JNICALL JavaMain(void * _args)
它负责加载要运行的java class,并调用class的main方法。处理步骤是:
1).InitializeJVM ->CreateJavaVM (即通过JNI调用JNI_CreateJavaVM),创建JVM。
2).LoadMainClass加载main class,并确保main方法的签名是正确的。
3).mainID = (*env)->GetStaticMethodID(env, mainClass, "main","([Ljava/lang/String;)V");通过JNI得到main方法的method信息。
4).mainArgs = NewPlatformStringArray(env, argv, argc);为main方法准备参数数组。
5).(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);通过JNI调用main方法。
6).ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;处理异常
7).DetachCurrentThread
8).DestroyJavaVM 销毁JVM。
了解了JVM的启动过程,很容易在C++代码中嵌入JVM,执行Java程序。下一步的工作,实现自己的JVM加载程序。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ictzxt/archive/2010/01/28/5263504.aspx
main->JLI_Launch
1.SelectVersion->LocateJRE,定位jre的位置。因为不同的操作系统上定位jre的方式不同,相关代码就和平台相关了,windows相关的一些代码在openjdk\jdk\src\windows下,而linux和solaris相关代码在openjdk\jdk\src\solaris下。这部分调用到的代码都在{os}\bin\java_md.c中。简单的说,windows中,LocateJRE要通过查找注册表来定位jre的位置,而Linux下可能需要读取环境变量等等,暂时不深入分析。
2.CreateExecutionEnvironment->GetJVMPath 得到jvm的路径,其实就是找到相应的动态链接库,具体到linux上,就是libjvm.so文件。
3.LoadJavaVM,Linux上是加载libjvm.so,windows上是加载jvm.dll,导出JNI_CreateJavaVM,JNI_GetDefaultJavaVMInitArgs等函数。
4.获取classpath。
5.ContinueInNewThread(&ifn, argc, argv, jarfile, classname, ret);在一个新线程中启动jvm。
ContinueInNewThreadd的功能是,调用GetDefaultJavaVMInitArgs(其实是调用JNI_GetDefaultJavaVMInitArgs)获取虚拟机初始化参数,设定线程栈的大小,创建java程序需要的各项参数。然后调用下面函数
ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args);
因为不同操作系统创建线程的方式不同,所以又进入os相关的代码,{os}\bin\java_md.c中的
int ContinueInNewThread0(int (JNICALL *continuation)(void *), jlong stack_size, void * args)函数。
阅读其代码,可知Linux上是通过pthread_create创建线程,Solaris通过thr_create创建线程,而windows则通过_beginthreadex创建线程。
在新线程中调用JavaMain 函数,即
openjdk\jdk\src\share\bin\main.c中的
int JNICALL JavaMain(void * _args)
它负责加载要运行的java class,并调用class的main方法。处理步骤是:
1).InitializeJVM ->CreateJavaVM (即通过JNI调用JNI_CreateJavaVM),创建JVM。
2).LoadMainClass加载main class,并确保main方法的签名是正确的。
3).mainID = (*env)->GetStaticMethodID(env, mainClass, "main","([Ljava/lang/String;)V");通过JNI得到main方法的method信息。
4).mainArgs = NewPlatformStringArray(env, argv, argc);为main方法准备参数数组。
5).(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);通过JNI调用main方法。
6).ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;处理异常
7).DetachCurrentThread
8).DestroyJavaVM 销毁JVM。
了解了JVM的启动过程,很容易在C++代码中嵌入JVM,执行Java程序。下一步的工作,实现自己的JVM加载程序。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ictzxt/archive/2010/01/28/5263504.aspx