src/share/bin/java.c::CheckJvmType
可通过以下三种方式指定jvm type
- 配置环境变量:JDK_ALTERNATE_VM=
- 通过命令行参数:-server | -client | -hotspot | -classic | -native | -green
- 通过命令行参数:-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;
}