《jdk8u源码分析》2.JLI_Launch

src/share/bin/java.c::JLI_Launch

/*
 * Entry point.
 */
int
JLI_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 */
)
{
    int mode = LM_UNKNOWN;
    char *what = NULL;
    char *cpath = 0;
    char *main_class = NULL;
    int ret;
    InvocationFunctions ifn;
    jlong start, end;
    char jvmpath[MAXPATHLEN];
    char jrepath[MAXPATHLEN];
    char jvmcfg[MAXPATHLEN];

    _fVersion = fullversion;
    _dVersion = dotversion;
    _launcher_name = lname;
    _program_name = pname;
    _is_java_args = javaargs;
    _wc_enabled = cpwildcard;
    _ergo_policy = ergo;

    //1.如果javaw==true,初始化MFC窗体
    //2.根据环境变量_JAVA_LAUNCHER_DEBUG的取值决定是否输出JVM Trace信息
    //  - 如果_JAVA_LAUNCHER_DEBUG==1,输出JVM Trace信息
    InitLauncher(javaw);
    //打印Launcher状态信息
    DumpState();
    //JVM Trace打印命令行参数
    if (JLI_IsTraceLauncher()) {
        int i;
        /**
         * Command line args:
         * argv[0] = java
         * argv[1] = -jar
         * argv[2] = test.jar
         * /
        printf("Command line args:\n");
        for (i = 0; i < argc ; i++) {
            printf("argv[%d] = %s\n", i, argv[i]);
        }
        AddOption("-Dsun.java.launcher.diag=true", NULL);
    }

    /*
     * Make sure the specified version of the JRE is running.
     *
     * There are three things to note about the SelectVersion() routine:
     *  1) If the version running isn't correct, this routine doesn't
     *     return (either the correct version has been exec'd or an error
     *     was issued).
     *  2) Argc and Argv in this scope are *not* altered by this routine.
     *     It is the responsibility of subsequent code to ignore the
     *     arguments handled by this routine.
     *  3) As a side-effect, the variable "main_class" is guaranteed to
     *     be set (if it should ever be set).  This isn't exactly the
     *     poster child for structured programming, but it is a small
     *     price to pay for not processing a jar file operand twice.
     *     (Note: This side effect has been disabled.  See comment on
     *     bugid 5030265 below.)
     */
    //加载Manifest判断JRE Version是否有效
    SelectVersion(argc, argv, &main_class);

    CreateExecutionEnvironment(&argc, &argv,
                               jrepath, sizeof(jrepath),
                               jvmpath, sizeof(jvmpath),
                               jvmcfg,  sizeof(jvmcfg));

    if (!IsJavaArgs()) {
    	//根据是否配置命令行参数:-XX:NativeMemoryTracking=
    	//决定是否设置环境变量:NMT_LEVEL_${PID}=value,用以内存跟踪
        SetJvmEnvironment(argc,argv);
    }

    ifn.CreateJavaVM = 0;
    ifn.GetDefaultJavaVMInitArgs = 0;

    if (JLI_IsTraceLauncher()) {
        start = CounterGet();
    }

	//1. 加载Microsoft C Runtime Library:%JRE_HOME%\\bin\\${jvmtype}\\jvm.dll
	//2. 加载jvm:%JRE_HOME%\\bin\\${jvmtype}\\jvm.dll
    if (!LoadJavaVM(jvmpath, &ifn)) {
        return(6);
    }

    if (JLI_IsTraceLauncher()) {
        end   = CounterGet();
    }

	//39449 micro seconds to LoadJavaVM
    JLI_TraceLauncher("%ld micro seconds to LoadJavaVM\n",
             (long)(jint)Counter2Micros(end-start));

	//移除命令行第一条命令:
	//argv[0] = C:\Tools\Java\open-jre1.8.0_202\bin\java.exe
    ++argv;
    --argc;

    if (IsJavaArgs()) {
        /* Preprocess wrapper arguments */
        //优化-J开头的命令行参数 && 展开-cp | -classpath配置项通配符
        TranslateApplicationArgs(jargc, jargv, &argc, &argv);
        //添加可选参数:
        //1. -Denv.class.path=	-> CLASSPATH
        //2. -Dapplication.home=	-> APP_HOME
	    //3. -Djava.class.path=	-> 取决于:宏定义变量JAVA_ARGS是否存在
        if (!AddApplicationOptions(appclassc, appclassv)) {
            return(1);
        }
    } else {
        /* Set default CLASSPATH */
        //如果环境变量:CLASSPATH 未定义,默认设置为当前目录:"."
        cpath = getenv("CLASSPATH");
        if (cpath == NULL) {
            cpath = ".";
        }
        //添加可选参数:-Djava.class.path=当前目录下的所有jar文件路径
        SetClassPath(cpath);
    }

    /* Parse command line options; if the return value of
     * ParseArguments is false, the program should exit.
     */
    //剥离以'-'开头的参数并设置相应的jvm可选参数
    //mode:LM_UNKNOWN | LM_CLASSPATH | LM_JAR
    //what:
    //1. 如果是jar包启动,what值为jar包路径:test.jar | D:\workdir\study\out\artifacts\test\test.jar
    //2. 如果是Class启动,what值为class完整名:com.johnjoe.study.Test
    if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath))
    {
        return(ret);
    }

    /* Override class path if -jar flag was specified */
    //jar包启动
    if (mode == LM_JAR) {
    	//重置可选参数:-Djava.class.path=
        SetClassPath(what);     /* Override class path */
    }

    /* set the -Dsun.java.command pseudo property */
    //添加可选参数:-Dsun.java.command=${java.exe完整路径} [ ${主程序完整名} | ${jar包}] ${命令行参数}
    SetJavaCommandLineProp(what, argc, argv);

    /* Set the -Dsun.java.launcher pseudo property */
    //添加可选参数:-Dsun.java.launcher=SUN_STANDARD
    SetJavaLauncherProp();

    /* set the -Dsun.java.launcher.* platform properties */
    //(**Linux only**)添加可选参数:-Dsun.java.launcher.pid=
    SetJavaLauncherPlatformProps();

    return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);
}

猜你喜欢

转载自blog.csdn.net/weixin_37477523/article/details/88117056