《jdk8u源码分析》6.2.ReadKnownVMs

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

/*
 * Read the jvm.cfg file and fill the knownJVMs[] array.
 *
 * The functionality of the jvm.cfg file is subject to change without
 * notice and the mechanism will be removed in the future.
 *
 * The lexical structure of the jvm.cfg file is as follows:
 *
 *     jvmcfg         :=  { vmLine }
 *     vmLine         :=  knownLine
 *                    |   aliasLine
 *                    |   warnLine
 *                    |   ignoreLine
 *                    |   errorLine
 *                    |   predicateLine
 *                    |   commentLine
 *     knownLine      :=  flag  "KNOWN"                  EOL
 *     warnLine       :=  flag  "WARN"                   EOL
 *     ignoreLine     :=  flag  "IGNORE"                 EOL
 *     errorLine      :=  flag  "ERROR"                  EOL
 *     aliasLine      :=  flag  "ALIASED_TO"       flag  EOL
 *     predicateLine  :=  flag  "IF_SERVER_CLASS"  flag  EOL
 *     commentLine    :=  "#" text                       EOL
 *     flag           :=  "-" identifier
 *
 * The semantics are that when someone specifies a flag on the command line:
 * - if the flag appears on a knownLine, then the identifier is used as
 *   the name of the directory holding the JVM library (the name of the JVM).
 * - if the flag appears as the first flag on an aliasLine, the identifier
 *   of the second flag is used as the name of the JVM.
 * - if the flag appears on a warnLine, the identifier is used as the
 *   name of the JVM, but a warning is generated.
 * - if the flag appears on an ignoreLine, the identifier is recognized as the
 *   name of a JVM, but the identifier is ignored and the default vm used
 * - if the flag appears on an errorLine, an error is generated.
 * - if the flag appears as the first flag on a predicateLine, and
 *   the machine on which you are running passes the predicate indicated,
 *   then the identifier of the second flag is used as the name of the JVM,
 *   otherwise the identifier of the first flag is used as the name of the JVM.
 * If no flag is given on the command line, the first vmLine of the jvm.cfg
 * file determines the name of the JVM.
 * PredicateLines are only interpreted on first vmLine of a jvm.cfg file,
 * since they only make sense if someone hasn't specified the name of the
 * JVM on the command line.
 *
 * The intent of the jvm.cfg file is to allow several JVM libraries to
 * be installed in different subdirectories of a single JRE installation,
 * for space-savings and convenience in testing.
 * The intent is explicitly not to provide a full aliasing or predicate
 * mechanism.
 */
jint
ReadKnownVMs(const char *jvmCfgName, jboolean speculative)
{
    FILE *jvmCfg;
    char line[MAXPATHLEN+20];
    int cnt = 0;
    int lineno = 0;
    jlong start, end;
    int vmType;
    char *tmpPtr;
    char *altVMName = NULL;
    char *serverClassVMName = NULL;
    static char *whiteSpace = " \t";
    if (JLI_IsTraceLauncher()) {
    	//获取定时器开始计数值
        start = CounterGet();
    }

	//打开%JRE_HOME%\lib\${arch}\jvm.cfg
    jvmCfg = fopen(jvmCfgName, "r");
    if (jvmCfg == NULL) {
      if (!speculative) {
      	//"Error: could not open `%s'"
        JLI_ReportErrorMessage(CFG_ERROR6, jvmCfgName);
        exit(1);
      } else {
        return -1;
      }
    }
    //遍历jvm.cfg每一行的内容
    while (fgets(line, sizeof(line), jvmCfg) != NULL) {
        vmType = VM_UNKNOWN;
        lineno++;
        //'#'号开始的注释过滤掉
        if (line[0] == '#')
            continue;
        //除去注释,所有有效配置行都应该以符号'-'开始,否则打印错误信息
        if (line[0] != '-') {
        	//"Warning: No leading - on line %d of `%s'"
            JLI_ReportErrorMessage(CFG_WARN2, lineno, jvmCfgName);
        }
        //knowVMs数组长度超过knownVMsLimit,扩容
        if (cnt >= knownVMsLimit) {
            GrowKnownVMs(cnt);
        }
        //移除行末换行符
        line[JLI_StrLen(line)-1] = '\0'; /* remove trailing newline */
        //字符指针移动指向第一个空白字符,line保留空格前的字符串:-server,tempPtr:' 'KNOWN
        //-server KNOWN
        //       ↑
        tmpPtr = line + JLI_StrCSpn(line, whiteSpace);
        //如果移动后的指针内容为0,打印异常信息
        if (*tmpPtr == 0) {
        	//"Warning: Missing VM type on line %d of `%s'"
            JLI_ReportErrorMessage(CFG_WARN3, lineno, jvmCfgName);
        } else {
            /* Null-terminate this string for JLI_StringDup below */
            *tmpPtr++ = 0;
            
            //字符指针移动到第一个非空白字符出,即tmpPtr内容就为参数值:KNOWN
        	//-server KNOWN
        	//        ↑
            tmpPtr += JLI_StrSpn(tmpPtr, whiteSpace);
            if (*tmpPtr == 0) {
            	//"Warning: Missing VM type on line %d of `%s'"
                JLI_ReportErrorMessage(CFG_WARN3, lineno, jvmCfgName);
            } else {
            	//设置vmType
                if (!JLI_StrCCmp(tmpPtr, "KNOWN")) {
                    vmType = VM_KNOWN;
                } else if (!JLI_StrCCmp(tmpPtr, "ALIASED_TO")) {
                	//获取别名
                    tmpPtr += JLI_StrCSpn(tmpPtr, whiteSpace);
                    if (*tmpPtr != 0) {
                        tmpPtr += JLI_StrSpn(tmpPtr, whiteSpace);
                    }
                    if (*tmpPtr == 0) {
                    	//"Warning: Missing VM type on line %d of `%s'"
                        JLI_ReportErrorMessage(CFG_WARN3, lineno, jvmCfgName);
                    } else {
                        /* Null terminate altVMName */
                        altVMName = tmpPtr;
                        tmpPtr += JLI_StrCSpn(tmpPtr, whiteSpace);
                        *tmpPtr = 0;
                        vmType = VM_ALIASED_TO;
                    }
                } else if (!JLI_StrCCmp(tmpPtr, "WARN")) {
                    vmType = VM_WARN;
                } else if (!JLI_StrCCmp(tmpPtr, "IGNORE")) {
                    vmType = VM_IGNORE;
                } else if (!JLI_StrCCmp(tmpPtr, "ERROR")) {
                    vmType = VM_ERROR;
                } else if (!JLI_StrCCmp(tmpPtr, "IF_SERVER_CLASS")) {
                    tmpPtr += JLI_StrCSpn(tmpPtr, whiteSpace);
                    if (*tmpPtr != 0) {
                        tmpPtr += JLI_StrSpn(tmpPtr, whiteSpace);
                    }
                    if (*tmpPtr == 0) {
                    	//"Warning: Missing server class VM on line %d of `%s'"
                        JLI_ReportErrorMessage(CFG_WARN4, lineno, jvmCfgName);
                    } else {
                        /* Null terminate server class VM name */
                        serverClassVMName = tmpPtr;
                        tmpPtr += JLI_StrCSpn(tmpPtr, whiteSpace);
                        *tmpPtr = 0;
                        vmType = VM_IF_SERVER_CLASS;
                    }
                } else {
                	//"Warning: Unknown VM type on line %d of `%s'"
                    JLI_ReportErrorMessage(CFG_WARN5, lineno, &jvmCfgName[0]);
                    vmType = VM_KNOWN;
                }
            }
        }
        
		//jvm.cfg[0] = ->-server<-
		//jvm.cfg[1] = ->-client<-
        JLI_TraceLauncher("jvm.cfg[%d] = ->%s<-\n", cnt, line);
        if (vmType != VM_UNKNOWN) {
            knownVMs[cnt].name = JLI_StringDup(line);//-server
            knownVMs[cnt].flag = vmType;//KNOWN
            switch (vmType) {
            default:
                break;
            case VM_ALIASED_TO:
                knownVMs[cnt].alias = JLI_StringDup(altVMName);
                JLI_TraceLauncher("    name: %s  vmType: %s  alias: %s\n",
                   knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias);
                break;
            case VM_IF_SERVER_CLASS:
                knownVMs[cnt].server_class = JLI_StringDup(serverClassVMName);
                JLI_TraceLauncher("    name: %s  vmType: %s  server_class: %s\n",
                    knownVMs[cnt].name, "VM_IF_SERVER_CLASS", knownVMs[cnt].server_class);
                break;
            }
            cnt++;
        }
    }
    fclose(jvmCfg);
    knownVMsCount = cnt;

    if (JLI_IsTraceLauncher()) {
    	//获取定时器结束计数值
        end   = CounterGet();
        //2326 micro seconds to parse jvm.cfg
        printf("%ld micro seconds to parse jvm.cfg\n",
               (long)(jint)Counter2Micros(end-start));
    }

    return cnt;
}

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

//获取定时器的计数值,用来计算时间差
jlong CounterGet()
{
    LARGE_INTEGER count;

    if (!counterInitialized) {
    	//获得机器内部计时器的时钟频率
        counterAvailable = QueryPerformanceFrequency(&counterFrequency);
        counterInitialized = JNI_TRUE;
    }
    if (!counterAvailable) {
        return 0;
    }
    //查询定时器的计数值,如果硬件里有定时器,它就会启动这个定时器,
    //并且不断获取定时器的值,这样的定时器精度,就跟硬件时钟的晶振一样精确的。
    QueryPerformanceCounter(&count);
    return (jlong)(count.QuadPart);
}

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

static void
GrowKnownVMs(int minimum)
{
    struct vmdesc* newKnownVMs;
    int newMax;
	
	//knownVMs扩容
	//1.如果knownVMsLimit为0,扩容为:INIT_MAX_KNOWN_VMS
	//2.如果knownVMsLimit不为0,扩容为:2 * knownVMsLimit
    newMax = (knownVMsLimit == 0 ? INIT_MAX_KNOWN_VMS : (2 * knownVMsLimit));
    //如果扩容后的容量不能满足要求,则将传入的值设为容量最大值
    if (newMax <= minimum) {
        newMax = minimum;
    }
    //为新的数组分配内存,将原有数据拷贝到新的数组中,并交换数组,重设knownVMsLimit
    newKnownVMs = (struct vmdesc*) JLI_MemAlloc(newMax * sizeof(struct vmdesc));
    if (knownVMs != NULL) {
        memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc));
    }
    JLI_MemFree(knownVMs);
    knownVMs = newKnownVMs;
    k = newMax;
}

src/share/bin/java.c

/* Maximum supported entries from jvm.cfg. */
#define INIT_MAX_KNOWN_VMS      10

/* Values for vmdesc.flag */
enum vmdesc_flag {
    VM_UNKNOWN = -1,
    VM_KNOWN,
    VM_ALIASED_TO,
    VM_WARN,
    VM_ERROR,
    VM_IF_SERVER_CLASS,
    VM_IGNORE
};

猜你喜欢

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