在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

OpenJDK9 Hotspot java 虚拟机入口

2016-8-29 13:25| 发布者: zhangjf| 查看: 648| 评论: 0

摘要: 假设 openjdk 源代码目录为 jdk9dev main函数 main 函数在 jdk9dev/jdk/src/java.base/share/native/launcher/main.c,它处理完命令行参数后跳转到 JLI_Launch 函数 int main(int argc, char** argv) { // ...

假设 openjdk 源代码目录为 jdk9dev

main函数

main 函数在 jdk9dev/jdk/src/java.base/share/native/launcher/main.c,它处理完命令行参数后跳转到 JLI_Launch 函数

  1. int main(int argc, char** argv) {
  2. // 处理命令行选项
  3. ...
  4. return JLI_Launch(margc, margv,
  5. sizeof(const_jargs) / sizeof(char *), const_jargs,
  6. appclassc, const_appclasspath,
  7. VERSION_STRING,
  8. DOT_VERSION,
  9. (const_progname != NULL) ? const_progname : *margv,
  10. (const_launcher != NULL) ? const_launcher : *margv,
  11. HAS_JAVA_ARGS,
  12. const_cpwildcard, const_javaw, const_ergo_class);
  13. }
复制代码
JLI_Launch

JLI_Launch 函数在 jdk9dev/jdk/src/java.base/share/native/libjli/java.c,
它调用 LoadJavaVM 加载 libjvm.dylib , 这个 libjvm.dylib 就是 hotspot 编译的产出!

  1. int JLI_Launch(...) {
  2. ...
  3. if (!LoadJavaVM(jvmpath, &ifn)) {
  4. return (6);
  5. }
  6. ...
  7. return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);
  8. }
复制代码
LoadJavaVM

在 mac osx 系统下 LoadJavaVM 在 jdk9dev/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c

  1. jboolean LoadJavaVM(const char* jvmpath, InvocationFunctions* ifn) {
  2. ...
  3. #ifndef STATIC_BUILD
  4. libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
  5. #else
  6. libjvm = dlopen(NULL, RTLD_FIRST);
  7. #endif
  8. ifn->CreateJavaVM = (CreateJavaVM_t)
  9. dlsym(libjvm, "JNI_CreateJavaVM");
  10. if (ifn->CreateJavaVM == NULL) {
  11. JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
  12. return JNI_FALSE;
  13. }
  14. ...
  15. }
复制代码

使用 dlopen 加载动态库并获取 JNI_CreateJavaVM 函数入口地址

JVMInit

在 mac osx 系统下 JVMInit 在jdk9dev/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c

熟悉 objc 的同学,对下面的代码应该会感到很亲切:

  1. int JVMInit(InvocationFunctions* ifn, jlong threadStackSize, ...) {
  2. ...
  3. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  4. {
  5. JavaLaunchHelper* launcher = [[[JavaLaunchHelper alloc] init] autorelease];
  6. [launcher performSelectorOnMainThread:@selector(launchJava:)
  7. withObject:[NSValue valueWithPointer:(void*)&args]
  8. waitUntilDone:YES];
  9. rslt = [launcher getReturnValue];
  10. }
  11. [pool drain];
  12. return rslt;
  13. ...
  14. }
复制代码

创建 JavaLaunchHelper 对象,并将控制流跳转到 launchJava

  1. @implementation JavaLauncherHelper
  2. -(int) launchJava:(NSValue*) argsValue {
  3. _returValue = JavaMain([argsValue pointerValue]);
  4. }
  5. @end
复制代码

呵呵,在 objc 环境短暂停留后控制留又回到 c/c++ 的世界-JavaMain

JavaMain

JavaMain 函数在 jdk9dev/jdk/src/java.base/share/native/libjli/java.c,
在 JavaMain 函数中 会初始化 java 虚拟机,查找 main class,获取 main class 的 main 方法,并开始执行 java 字节码

  1. int JNICALL JavaMain(void* _args) {
  2. ...
  3. // 初始化 jvm
  4. if (!InitializeJVM(&vm, &env, &ifn)) {
  5. ...
  6. }
  7. ...
  8. // 加载 main class
  9. mainClass = LoadMainClass(env, mode, what);
  10. ...
  11. // 获取 main 方法
  12. mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
  13. "([Ljava/lang/String;)V");
  14. ...
  15. // 调用 main 方法
  16. (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
  17. LEAVE();
  18. }
复制代码

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-7-8 00:57

Copyright 2015-2025 djqfx

返回顶部