Startup of Java Virtual Machine and program running

Source: Internet
Author: User

Startup of Java Virtual Machine and program running

This article is from the perspective of OpenJDK source code.

java -classpath . hello

Later, how does java.exe execute from the main function, start the virtual machine, and execute the code in the bytecode.

Lab Environment

To understand how a system runs, you can't simply see it. You must actually run, debug, and modify the system to understand the system's action methods.

At first, I used Visual Studio 2010 to debug and run OpenJDK-Research, a GitHub project, on windows 7 64-bit platform. But later I found that this project only compiled the HotSpot virtual machine,java.exeNot compiled.

First, we can understandjava.exeAnd virtual machines. The HotSpot compiled by Visual Studio is a virtual machine and is used as a dynamic link library.java.exeLoaded.java.exeResolves the parameters and loads the Virtual Machine Link Library. It needs to call functions in the virtual machine to execute Java program functions. Therefore, you cannot find the Startup Program in the source code of HotSpot.mainFunction, originally in openjdk7, the virtual machine has an initiator in the directoryopenjdk/hotspot/src/share/tools/launcher/java.cThe main function can be found, but in openjdk8, this starter is missing and put inopenjdk/jdkDirectory insteadopenjdk/hotspotDirectory, causing harm to our learning process.

So I debugged it on the linux platform later, because on the windows platform, I have never compiled the entire openjdk8 successfully and cannot compile it.java.exe, Only compiledhotspotYou cannot see the execution of the main function. For more information about how to compile and debug openjdk8 on the linux platform, refer to another article on how to compile openjdk8on Ubuntu 12.04.

Call Stack
jdk8u/jdk/src/share/bin/main.c::WinMain/main  jdk8u/jdk/src/share/bin/java.c::JLI_Launch    jdk8u/jdk/src/solaris/bin/java_md_solinux.c::LoadJavaVM # Load JVM Library: libjvm.so    jdk8u/jdk/src/solaris/bin/java_md_solinux.c::JVMInit # Create JVM      jdk8u/jdk/src/share/bin/java.c::ContinueInNewThread        jdk8u/jdk/src/solaris/bin/java_md_solinux.c::ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args);          pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args)            jdk8u/jdk/src/share/bin/java.c::JavaMain              jdk8u/jdk/src/share/bin/java.c::InitializeJVM                jdk8u\hotspot\src\share\vm\prims\jni.cpp::JNI_CreateJavaVM
Execution Process
  • Main. c (jdk8u/jdk/src/share/bin/main. c)
    #ifdef JAVAWchar **__initenv;int WINAPIWinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow){    int margc;    char** margv;    const jboolean const_javaw = JNI_TRUE;    __initenv = _environ;#else /* JAVAW */intmain(int argc, char **argv){    int margc;    char** margv;    const jboolean const_javaw = JNI_FALSE;#endif /* JAVAW */#ifdef _WIN32    {        int i = 0;        if (getenv(JLDEBUG_ENV_ENTRY) != NULL) {            printf("Windows original main args:\n");            for (i = 0 ; i < __argc ; i++) {                printf("wwwd_args[%d] = %s\n", i, __argv[i]);            }        }    }    JLI_CmdToArgs(GetCommandLine());    margc = JLI_GetStdArgc();    // add one more to mark the end    margv = (char **)JLI_MemAlloc((margc + 1) * (sizeof(char *)));    {        int i = 0;        StdArg *stdargs = JLI_GetStdArgs();        for (i = 0 ; i < margc ; i++) {            margv[i] = stdargs[i].arg;        }        margv[i] = NULL;    }#else /* *NIXES */    margc = argc;    margv = argv;#endif /* WIN32 */    return JLI_Launch(margc, margv,                   sizeof(const_jargs) / sizeof(char *), const_jargs,                   sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,                   FULL_VERSION,                   DOT_VERSION,                   (const_progname != NULL) ? const_progname : *margv,                   (const_launcher != NULL) ? const_launcher : *margv,                   (const_jargs != NULL) ? JNI_TRUE : JNI_FALSE,                   const_cpwildcard, const_javaw, const_ergo_class);}

    This is the legendmainIt can be seen that the function executes different code segments for the operating system to determine whether to use Windows, and finally callsJLI_LaunchFunction.

    • JLI_Lanuch (jdk8u/jdk/src/share/bin/java. c)
      intJLI_Launch(int argc, char ** argv,              /* main argc, argc */        int jargc, const char** jargv,          /* java args */        int appclassc, const char** appclassv,  /* app classpath */        const char* fullversion,                /* full version defined */        const char* dotversion,                 /* dot version defined */        const char* pname,                      /* program name */        const char* lname,                      /* launcher name */        jboolean javaargs,                      /* JAVA_ARGS */        jboolean cpwildcard,                    /* classpath wildcard*/        jboolean javaw,                         /* windows-only javaw */        jint ergo                               /* ergonomics class policy */){...    if (!LoadJavaVM(jvmpath, &ifn)) {        return(6);    }...    return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);}

      Here we can see the meaning of each JLI_Lanuch parameter. I have listed the key code, whereLoadJavaVMLoad and initialize the dynamic link library of the VM.ifnThe function pointer in the HotSpot VM is like this to the initiatorjavaProvides functions.

      • LoadJavaVM (jdk8u/jdk/src/solaris/bin/java_md_solinux.c)

        This function involves a dynamic link library. different operating systems have different interfaces. This function is for linux.

        jbooleanLoadJavaVM(const char *jvmpath, InvocationFunctions *ifn){    ...    libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);    ...    ifn->CreateJavaVM = (CreateJavaVM_t)    dlsym(libjvm, "JNI_CreateJavaVM");    ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)    dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");    ifn->GetCreatedJavaVMs = (GetCreatedJavaVMs_t)        dlsym(libjvm, "JNI_GetCreatedJavaVMs");  ...

        Here we can see the code for loading the dynamic link library and initializing the FN data structure. In my debugging version,javapathPoint to the previously compiled Dynamic Link Libraryjdk8u/build/fastdebug/jdk/lib/i386/server/libjvm.so.

        • JVM_Init (jdk8u/jdk/src/solaris/bin/java_md_solinux.c)

          BackJLI_LanuchFunction.JVM_InitThis function starts a new thread.

          intJVMInit(InvocationFunctions* ifn, jlong threadStackSize,        int argc, char **argv,        int mode, char *what, int ret){    ShowSplashScreen();    return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);}

          ContinueInNewThreadWill call another functionContinueInNewThread0Start thread and executeJavaMainFunction:

          intContinueInNewThread0(int (JNICALL *continuation)(void *), jlong stack_size, void * args) {...    if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) {      void * tmp;      pthread_join(tid, &tmp);      rslt = (int)tmp;    } else {     /*      * Continue execution in current thread if for some reason (e.g. out of      * memory/LWP)  a new thread can't be created. This will likely fail      * later in continuation as JNI_CreateJavaVM needs to create quite a      * few new threads, anyway, just give it a try..      */      rslt = continuation(args);    }...
          • JavaMain (jdk8u/jdk/src/share/bin/java. c)

            This function initializes the virtual machine, loads various types, and executesmainFunction. The annotations are detailed.

            int JNICALLJavaMain(void * _args){    JavaMainArgs *args = (JavaMainArgs *)_args;    int argc = args->argc;    char **argv = args->argv;    int mode = args->mode;    char *what = args->what;    InvocationFunctions ifn = args->ifn;    JavaVM *vm = 0;    JNIEnv *env = 0;    jclass mainClass = NULL;    jclass appClass = NULL; // actual application class being launched    jmethodID mainID;    jobjectArray mainArgs;    int ret = 0;    jlong start, end;    RegisterThread();    /* Initialize the virtual machine */    start = CounterGet();    if (!InitializeJVM(&vm, &env, &ifn)) {        JLI_ReportErrorMessage(JVM_ERROR1);        exit(1);    }    ...    ret = 1;    /*     * Get the application's main class.     *     * See bugid 5030265.  The Main-Class name has already been parsed     * from the manifest, but not parsed properly for UTF-8 support.     * Hence the code here ignores the value previously extracted and     * uses the pre-existing code to reextract the value.  This is     * possibly an end of release cycle expedient.  However, it has     * also been discovered that passing some character sets through     * the environment has "strange" behavior on some variants of     * Windows.  Hence, maybe the manifest parsing code local to the     * launcher should never be enhanced.     *     * Hence, future work should either:     *     1)   Correct the local parsing code and verify that the     *          Main-Class attribute gets properly passed through     *          all environments,     *     2)   Remove the vestages of maintaining main_class through     *          the environment (and remove these comments).     *     * This method also correctly handles launching existing JavaFX     * applications that may or may not have a Main-Class manifest entry.     */    mainClass = LoadMainClass(env, mode, what);    CHECK_EXCEPTION_NULL_LEAVE(mainClass);    /*     * In some cases when launching an application that needs a helper, e.g., a     * JavaFX application with no main method, the mainClass will not be the     * applications own main class but rather a helper class. To keep things     * consistent in the UI we need to track and report the application main class.     */    appClass = GetApplicationClass(env);    NULL_CHECK_RETURN_VALUE(appClass, -1);    /*     * PostJVMInit uses the class name as the application name for GUI purposes,     * for example, on OSX this sets the application name in the menu bar for     * both SWT and JavaFX. So we'll pass the actual application class here     * instead of mainClass as that may be a launcher or helper class instead     * of the application class.     */    PostJVMInit(env, appClass, vm);    /*     * The LoadMainClass not only loads the main class, it will also ensure     * that the main method's signature is correct, therefore further checking     * is not required. The main method is invoked here so that extraneous java     * stacks are not in the application stack trace.     */    mainID = (*env)->GetStaticMethodID(env, mainClass, "main",                                       "([Ljava/lang/String;)V");    CHECK_EXCEPTION_NULL_LEAVE(mainID);    /* Build platform specific argument array */    mainArgs = CreateApplicationArgs(env, argv, argc);    CHECK_EXCEPTION_NULL_LEAVE(mainArgs);    /* Invoke main method. */    (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);    /*     * The launcher's exit code (in the absence of calls to     * System.exit) will be non-zero if main threw an exception.     */    ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;    LEAVE();}

            Note that the InitializeJVM function will call the previously initializedifnIn the data structureCreateJavaVMFunction.

            • InitializeJVM (jdk8u/jdk/src/share/bin/java. c: InitializeJVM)
              static jbooleanInitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn){    JavaVMInitArgs args;    jint r;    memset(&args, 0, sizeof(args));    args.version  = JNI_VERSION_1_2;    args.nOptions = numOptions;    args.options  = options;    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);    }    r = ifn->CreateJavaVM(pvm, (void **)penv, &args);    JLI_MemFree(options);    return r == JNI_OK;}

              ifn->CreateJavaVMPoint to the dynamic Connection Library of the Virtual MachineJNI_CreateJavaVMFunction, this function will actually create a virtual machine.

              • JNI_CreateJavaVM (jdk8u \ hotspot \ src \ share \ vm \ prims \ jni. cpp)
                _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) {  ...    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);    *(JNIEnv**)penv = thread->jni_environment();    // Tracks the time application was running before GC    RuntimeService::record_application_start();    // Notify JVMTI    if (JvmtiExport::should_post_thread_life()) {       JvmtiExport::post_thread_start(thread);    }    ...  }  ...}

                Thecreate_vmA function is the key to VM initialization. It initializes most of the VM's components.

                This function is located injdk8u\hotspot\src\share\vm\prims\jni.cpp.

                The first function that I used to debug in Windows is the HotSpot dynamic link library.JNI_CreateJavaVM, The previous calls are all located injava.exeCode. Because Windowsjava.exeWe didn't compile it by ourselves, and we couldn't see the call relationship in it. As shown in:


                At the same time, we can see two threads <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4KPHA + CjxpbWcgc3JjPQ = "http://www.2cto.com/uploadfile/Collfiles/20140823/20140823094904303.png" alt = "">



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.