Hotspot源码解析-第五章

第五章

5.1 初始化Java虚拟机

5.1.1 java.c

5.1.1.1 InitializeJVM
/*
 * Initializes the Java Virtual Machine. Also frees options array when
 * finished.
 * 初始化java 虚拟机,完成后释放options数组,option就是虚拟机启动时设置的参数,这里初始化完了,当然要释放咯
 */
static jboolean
InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn)
{
    JavaVMInitArgs args;
    jint r;
    // 将args所代表的内存空间,用0填充
    memset(&args, 0, sizeof(args));
    // 变量赋值
    args.version  = JNI_VERSION_1_2;  // 版本
    args.nOptions = numOptions;  // option选项数量
    args.options  = options;   // option选项数组/指针
    args.ignoreUnrecognized = JNI_FALSE;
    // 日志打印
    if (JLI_IsTraceLauncher()) {
        int i = 0;
        printf("JavaVM args:\n    ");
        printf("version 0x%08lx, ", (long)args.version);
        printf("ignoreUnrecognized is %s, ",
               args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE");
        printf("nOptions is %ld\n", (long)args.nOptions);
        for (i = 0; i < numOptions; i++)
            printf("    option[%2d] = '%s'\n",
                   i, args.options[i].optionString);
    }
    // CreateJavaVM函数在章节3.3.1.1已经定义了,实际指向的是JNI_CreateJavaVM函数,JNI_开头的函数,都定义在jni.cpp文件中,通过CreateJavaVM函数真正创建Java虚拟机
    r = ifn->CreateJavaVM(pvm, (void **)penv, &args);
    JLI_MemFree(options);  // 初始化后,options没什么意义了,释放资源
    return r == JNI_OK;
}

5.2 创建Java虚拟机

5.2.1 jni.cpp

5.2.1.1 JNI_CreateJavaVM

这个函数中用到了很多宏定义,这也就是c++强大的地方,当然对于程序员来说也是恶心的地方,我们暂且不管这些宏定义的具体涵义,跟着我的注释走,大家都能明白。

// 这行的宏定义,就把它想像成一个返回jint的函数:jint  JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) {}
_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) {
#ifndef USDT2  // 日志记录用,不管了
  HS_DTRACE_PROBE3(hotspot_jni, CreateJavaVM__entry, vm, penv, args);
#else /* USDT2 */  // 日志记录用,不管了
  HOTSPOT_JNI_CREATEJAVAVM_ENTRY(
                                 (void **) vm, penv, args);
#endif /* USDT2 */

  jint result = JNI_ERR;
  DT_RETURN_MARK(CreateJavaVM, jint, (const jint&)result);  // 日志记录用,不管了

 /*
 * 这一段是检验Atomic::xchg(汇编命令:原子性更改变量的值)是否可用,jvm用Atomic::xchg来
 * 实现synchronization同步。
 */
#if defined(ZERO) && defined(ASSERT)
  {
    jint a = 0xcafebabe;
    jint b = Atomic::xchg(0xdeadbeef, &a);
    void *c = &a;
    void *d = Atomic::xchg_ptr(&b, &c);
    assert(a == (jint) 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works");
    assert(c == &b && d == &a, "Atomic::xchg_ptr() works");
  }
#endif // ZERO && ASSERT

  // 原子操作:设置vm_created为1,防止其他线程创建jvm
  if (Atomic::xchg(1, &vm_created) == 1) {
    return JNI_EEXIST;   // 已经创建,或者在创建过程中
  }
  // 原子操作:设置safe_to_recreate_vm为0,防止重试
  if (Atomic::xchg(0, &safe_to_recreate_vm) == 0) {
    return JNI_ERR;  // 尝试失败后就不允许重试
  }

  assert(vm_created == 1, "vm_created is true during the creation");

  bool can_try_again = true;
  /* 调用Threads::create_vm,真正创建jvm,在这个函数中主要做以下几件事,现在先梳理一下脉络,后面也会讲细节:
  * 1、输入输出流初始化
  * 2、os模块初始化
  * 3、初始化系统属性
  * 4、jdk版本初始化
  * 5、java参数解析
  * 6、TLS初始化
  * 7、创建系统级class
  * 8、创建一个java级线程,与当前主线程一一对应起来
  * 9、初始化jvm涉及的各个模块
  * 10、创建并启动vm自身线程,用于处理一些幕后的操作
  * 11、初始化jvmti(jvm的黑匣子,记录jvm的运行情况,可以通过调用jvmti的接口对jvm进行管理)
  * 12、初始化系统自带的类,比如String、System、Thread等
  * 13、初始化内存空间:元空间、堆空间、栈空间
  * 14、信号处理初始化
  * 15、其他
  */
  result = Threads::create_vm((JavaVMInitArgs*) args, &can_try_again);
  if (result == JNI_OK) {  // 创建成功
    JavaThread *thread = JavaThread::current(); // 当前线程,其实就是主线程
    /* thread is thread_in_vm here */
    *vm = (JavaVM *)(&main_vm); // 将vm指针指向create_vm中创建的vm,后续操作要用
    *(JNIEnv**)penv = thread->jni_environment(); // 同样的penv指针指向create_vm中创建的vm的环境

    // 这一行就是记录日志,不重要
    RuntimeService::record_application_start();

    // 通知 JVMTI(jvm的黑匣子,记录jvm的运行情况,可以通过调用jvmti的接口对jvm进行管理)
    if (JvmtiExport::should_post_thread_life()) {
       JvmtiExport::post_thread_start(thread);
    }
    // 这一行也不需要关注
    post_thread_start_event(thread);

#ifndef PRODUCT
  #ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED
    #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
  #endif

    // Check if we should compile all classes on bootclasspath
    // CompileTheWorld 默认值定义在globals.hpp中,默认值是false,就是判断是否要对bootclasspath上的所有类做全局编译,默认不需要,先跳过这里
    if (CompileTheWorld) ClassLoader::compile_the_world();
    if (ReplayCompiles) ciReplay::replay(thread);

    // Some platforms (like Win*) need a wrapper around these test
    // functions in order to properly handle error conditions.
    CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(test_error_handler);
    CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(execute_internal_vm_tests);
#endif

    // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving.
    ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native);
  } else { // create_vm创建vm失败
    if (can_try_again) {  // 判断是否可以重试
	 // 可重试就把safe_to_recreate_vm设置为1
      safe_to_recreate_vm = 1;
    }

    // 创建失败了,要重置vm_created
    *vm = 0;
    *(JNIEnv**)penv = 0;
    // 释放创建过程vm_created空间
    OrderAccess::release_store(&vm_created, 0);
  }
  // 返回结果
  return result;
}

你可能感兴趣的:(Java虚拟机,java)