《jdk8u源码分析》6.3.CheckJvmType ergo

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

可通过以下三种方式指定jvm type

  1. 配置环境变量:JDK_ALTERNATE_VM=
  2. 通过命令行参数:-server | -client | -hotspot | -classic | -native | -green
  3. 通过命令行参数:-XXaltjvm= | -J-XXaltjvm=
/*
 * Checks the command line options to find which JVM type was
 * specified.  If no command line option was given for the JVM type,
 * the default type is used.  The environment variable
 * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also
 * checked as ways of specifying which JVM type to invoke.
 */
char *
CheckJvmType(int *pargc, char ***argv, jboolean speculative) {
    int i, argi;
    int argc;
    char **newArgv;
    int newArgvIdx = 0;
    int isVMType;
    int jvmidx = -1;
    char *jvmtype = getenv("JDK_ALTERNATE_VM");

    argc = *pargc;

    /* To make things simpler we always copy the argv array */
    newArgv = JLI_MemAlloc((argc + 1) * sizeof(char *));

    /* The program name is always present */
    newArgv[newArgvIdx++] = (*argv)[0];

    for (argi = 1; argi < argc; argi++) {
        char *arg = (*argv)[argi];
        isVMType = 0;
		
		//如果参数是jvm编译时定义在:JAVA_ARGS且不以'-'开始,
		//直接存储在新的数组指针newArgv中
        if (IsJavaArgs()) {
            if (arg[0] != '-') {
                newArgv[newArgvIdx++] = arg;
                continue;
            }
        } else {
            //argv[7] = -classpath
            //argv[8] = xx1.jar;xx2.jar;...
            //argv[9] = com.johnjoe.study.Test
            //argv[10] = -cp
            //argv[11] = xxx.jar
            //因为argv中-classpath和-cp的特殊处理
            if (JLI_StrCmp(arg, "-classpath") == 0 ||
                JLI_StrCmp(arg, "-cp") == 0) {
                newArgv[newArgvIdx++] = arg;
                argi++;
                //存储-classpath | -cp 的值
                if (argi < argc) {
                    newArgv[newArgvIdx++] = (*argv)[argi];
                }
                continue;
            }
            if (arg[0] != '-') break;
        }

        /* Did the user pass an explicit VM type? */
        //搜索knownVMs里面是否有与arg匹配的name,如果有返回其索引,否则返回-1
        //如:arg = [-server | -client | -hotspot | -classic | -native | -green]等...
        i = KnownVMIndex(arg);
        if (i >= 0) {
            jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */
            isVMType = 1;
            *pargc = *pargc - 1;
        }

        /* Did the user specify an "alternate" VM? */
        //判断用户是否配置了altjvm,如果配置了,以用户配置的为准
        else if (JLI_StrCCmp(arg, "-XXaltjvm=") == 0 || JLI_StrCCmp(arg, "-J-XXaltjvm=") == 0) {
            isVMType = 1;
            //移除[-XXaltjvm= | -J-XXaltjvm=]
            jvmtype = arg+((arg[1]=='X')? 10 : 12);
            jvmidx = -1;
        }
		
		//过滤-server | -client | -XXaltjvm= | -J-XXaltjvm= 等配置vmType的参数
        if (!isVMType) {
            newArgv[newArgvIdx++] = arg;
        }
    }

    /*
     * Finish copying the arguments if we aborted the above loop.
     * NOTE that if we aborted via "break" then we did NOT copy the
     * last argument above, and in addition argi will be less than
     * argc.
     */
    //如果for循环被break掉,继续拷贝剩余的参数newArgv数组中
    while (argi < argc) {
        newArgv[newArgvIdx++] = (*argv)[argi];
        argi++;
    }

    /* argv is null-terminated */
    //初始化时定义数组长度为argvc+1,因过滤了部分参数,这里将数组最后一个元素置零
    newArgv[newArgvIdx] = 0;

    /* Copy back argv */
    //将新的参数数组和长度重新赋值给命令行参数素组
    *argv = newArgv;
    *pargc = newArgvIdx;

    /* use the default VM type if not specified (no alias processing) */
    //未通过命令指定jvm type,默认使用jvm.cfg第一条配置:-server KNOWN
    if (jvmtype == NULL) {
      char* result = knownVMs[0].name+1;
      /* Use a different VM type if we are on a server class machine? */
      //如果jvm.cfg第一条配置flag为:VM_IF_SERVER_CLASS 且 系统为服务器类机器
      //则vm type为第一条配置的server_class值(去除首字符)
      //e.g.: -client VM_IF_SERVER_CLASS **-server**
      if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
          (ServerClassMachine() == JNI_TRUE)) {
        result = knownVMs[0].server_class+1;
      }
      //Default VM: server
      JLI_TraceLauncher("Default VM: %s\n", result);
      return result;
    }

    /* if using an alternate VM, no alias processing */
    //如果是通过参数 -XXaltjvm= | -J-XXaltjvm= | 默认读取jvm.cfg第一条 指定的jvm type 直接返回jvmtype
    if (jvmidx < 0)
      return jvmtype;

    /* Resolve aliases first */
    //如果是通过参数 -server | -client 等 指定的jvm type, 
    //需要处理别名配置:VM_ALIASED_TO 获取真实的jvm type
    {
      int loopCount = 0;
      while (knownVMs[jvmidx].flag == VM_ALIASED_TO) {
      	//获取实际指向的配置如:-server | -client
        int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias);

        if (loopCount > knownVMsCount) {
          if (!speculative) {
          	//"Error: Corrupt jvm.cfg file; cycle in alias list."
            JLI_ReportErrorMessage(CFG_ERROR1);
            exit(1);
          } else {
            return "ERROR";
            /* break; */
          }
        }

        if (nextIdx < 0) {
          if (!speculative) {
          	//"Error: Unable to resolve VM alias %s"
            JLI_ReportErrorMessage(CFG_ERROR2, knownVMs[jvmidx].alias);
            exit(1);
          } else {
            return "ERROR";
          }
        }
        jvmidx = nextIdx;
        //获取真实的jvm type,如果flag == VM_ALIASED_TO则继续获取
        jvmtype = knownVMs[jvmidx].name+1;
        loopCount++;
      }
    }
	
	
    switch (knownVMs[jvmidx].flag) {
    case VM_WARN:
        if (!speculative) {
        	//"Warning: %s VM not supported; %s VM will be used"
            JLI_ReportErrorMessage(CFG_WARN1, jvmtype, knownVMs[0].name + 1);
        }
        /* fall through */
    case VM_IGNORE:
    	//重新将jvm type设置为第一条配置(去首字符'-')
        jvmtype = knownVMs[jvmidx=0].name + 1;
        /* fall through */
    case VM_KNOWN:
        break;
    case VM_ERROR:
        if (!speculative) {
        	//"Error: %s VM not supported"
            JLI_ReportErrorMessage(CFG_ERROR3, jvmtype);
            //直接退出进程
            exit(1);
        } else {
            return "ERROR";
        }
    }

    return jvmtype;
}

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

jboolean
IsJavaArgs()
{
	//参数是否来自于编译时定义的宏变量:JAVA_ARGS
    return _is_java_args;
}

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

/* Returns index of VM or -1 if not found */
static int
KnownVMIndex(const char* name)
{
    int i;
    //如果参数名前两个字母是-J,指针向后移2个字符,即移除-J
    if (JLI_StrCCmp(name, "-J") == 0) name += 2;
    //获取name在knownVMs数组中的索引,为找到返回-1
    for (i = 0; i < knownVMsCount; i++) {
        if (!JLI_StrCmp(name, knownVMs[i].name)) {
            return i;
        }
    }
    return -1;
}

src/windows/bin/java_md.c::ServerClassMachine

jboolean
ServerClassMachine() {
	//@see: 4.DumpState
    return (GetErgoPolicy() == ALWAYS_SERVER_CLASS) ? JNI_TRUE : JNI_FALSE;
}

猜你喜欢

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