这一章是接着章节7.1 启动参数解析
来讲的,第七章中对这块参数的解析有些遗漏,现在补充下,主要是针对内存分配参数的解析做重点介绍
这个方法的入口还是在章节7.1.1.1 Arguments::parse
这个函数中
jint Arguments::parse_vm_init_args(const JavaVMInitArgs* args) {
// For components of the system classpath.
SysClassPath scp(Arguments::get_sysclasspath());
bool scp_assembly_required = false;
// Save default settings for some mode flags
Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
Arguments::_UseOnStackReplacement = UseOnStackReplacement;
Arguments::_ClipInlining = ClipInlining;
Arguments::_BackgroundCompilation = BackgroundCompilation;
// Setup flags for mixed which is the default
set_mode_flags(_mixed);
// 解析 JAVA_TOOL_OPTIONS 环境变量
jint result = parse_java_tool_options_environment_variable(&scp, &scp_assembly_required);
if (result != JNI_OK) {
return result;
}
// 解析 JavaVMInitArgs 结构,重点在这,看8.1.1.2
result = parse_each_vm_init_arg(args, &scp, &scp_assembly_required, Flag::COMMAND_LINE);
if (result != JNI_OK) {
return result;
}
// 解析 _JAVA_OPTIONS 环境变量
result = parse_java_options_environment_variable(&scp, &scp_assembly_required);
if (result != JNI_OK) {
return result;
}
// 这一步就是保证在进行最终参数处理之前,处理器和内存资源已正确配置
os::init_container_support();
// 完成参数解析工作,做一些收尾工作,这里不细讲了,重点讲解析
result = finalize_vm_init_args(&scp, scp_assembly_required);
if (result != JNI_OK) {
return result;
}
return JNI_OK;
}
jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
SysClassPath* scp_p,
bool* scp_assembly_required_p,
Flag::Flags origin) {
// 指向剩余选项问题,其实就是指向=后面的值
const char* tail;
// 遍历选项参数
for (int index = 0; index < args->nOptions; index++) {
bool is_absolute_path = false; // for -agentpath vs -agentlib
const JavaVMOption* option = args->options + index;
if (!match_option(option, "-Djava.class.path", &tail) &&
!match_option(option, "-Dsun.java.command", &tail) &&
!match_option(option, "-Dsun.java.launcher", &tail)) {
// 将所有的jvm 选项参数(除了-Djava.class.path,-Dsun.java.command,-Dsun.java.launcher 这三个,因为它们都有自己的PerfData字符串常量对象,可以看`章节2.1.2.1`)作为字符串添加到jvm_args字符串数组中
build_jvm_args(option->optionString);
}
/* -verbose:[class/gc/jni],就是确定是否输出对应的日志信息
* 命令格式如:java -verbose[:flag] [argument]
* flag是参数,argument是可选的参数。启用Java-verbose的方式有以下几种:
* -verbose:gc:输出垃圾收集器的日志信息
* -verbose:class:输出类加载器加载Class的详细信息
* -verbose:jni:输出jni绑定日志
*/
if (match_option(option, "-verbose", &tail)) {
if (!strcmp(tail, ":class") || !strcmp(tail, "")) {
FLAG_SET_CMDLINE(bool, TraceClassLoading, true);
FLAG_SET_CMDLINE(bool, TraceClassUnloading, true);
} else if (!strcmp(tail, ":gc")) {
FLAG_SET_CMDLINE(bool, PrintGC, true);
} else if (!strcmp(tail, ":jni")) {
FLAG_SET_CMDLINE(bool, PrintJNIResolving, true);
}
// -da / -ea / -disableassertions / -enableassertions
// 按指定的粒度(程序包名称|类名称),开启/关闭断言功能 e就是开,d就是关
} else if (match_option(option, user_assertion_options, &tail, true)) {
bool enable = option->optionString[1] == 'e'; // char after '-' is 'e'
if (*tail == '\0') {
JavaAssertions::setUserClassDefault(enable);
} else {
assert(*tail == ':', "bogus match by match_option()");
JavaAssertions::addOption(tail + 1, enable);
}
// 开启/关闭系统断言功能 e就是开,d就是关
} else if (match_option(option, system_assertion_options, &tail, false)) {
bool enable = option->optionString[1] == 'e'; // char after '-' is 'e'
JavaAssertions::setSystemClassDefault(enable);
// -bootclasspath: 替换class path,这个慎用,尽量别用
} else if (match_option(option, "-Xbootclasspath:", &tail)) {
scp_p->reset_path(tail);
*scp_assembly_required_p = true;
// -bootclasspath/a: 在原class path 上追加,正常情况,用这个就行
} else if (match_option(option, "-Xbootclasspath/a:", &tail)) {
scp_p->add_suffix(tail);
*scp_assembly_required_p = true;
// -bootclasspath/p: 在原class path 前面添加
} else if (match_option(option, "-Xbootclasspath/p:", &tail)) {
scp_p->add_prefix(tail);
*scp_assembly_required_p = true;
// -Xrun:这个参数已经不用了
} else if (match_option(option, "-Xrun", &tail)) {
if (tail != NULL) {
const char* pos = strchr(tail, ':');
size_t len = (pos == NULL) ? strlen(tail) : pos - tail;
char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1, mtInternal), tail, len);
name[len] = '\0';
char *options = NULL;
if(pos != NULL) {
size_t len2 = strlen(pos+1) + 1; // options start after ':'. Final zero must be copied.
options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtInternal), pos+1, len2);
}
#if !INCLUDE_JVMTI
if ((strcmp(name, "hprof") == 0) || (strcmp(name, "jdwp") == 0)) {
jio_fprintf(defaultStream::error_stream(),
"Profiling and debugging agents are not supported in this VM\n");
return JNI_ERR;
}
#endif // !INCLUDE_JVMTI
add_init_library(name, options);
}
// -agentlib and -agentpath:加载本机代理库参数,主要用于jmx、远程调试
} else if (match_option(option, "-agentlib:", &tail) ||
(is_absolute_path = match_option(option, "-agentpath:", &tail))) {
if(tail != NULL) {
const char* pos = strchr(tail, '=');
size_t len = (pos == NULL) ? strlen(tail) : pos - tail;
char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1, mtInternal), tail, len);
name[len] = '\0';
char *options = NULL;
if(pos != NULL) {
size_t length = strlen(pos + 1) + 1;
options = NEW_C_HEAP_ARRAY(char, length, mtInternal);
jio_snprintf(options, length, "%s", pos + 1);
}
#if !INCLUDE_JVMTI
if (valid_hprof_or_jdwp_agent(name, is_absolute_path)) {
jio_fprintf(defaultStream::error_stream(),
"Profiling and debugging agents are not supported in this VM\n");
return JNI_ERR;
}
#endif // !INCLUDE_JVMTI
add_init_agent(name, options, is_absolute_path);
}
// -javaagent:加载 Java 编程语言代理,就是在main方法执行前先执行这个代理jar(因为代理必须打包成jar)
} else if (match_option(option, "-javaagent:", &tail)) {
#if !INCLUDE_JVMTI
jio_fprintf(defaultStream::error_stream(),
"Instrumentation agents are not supported in this VM\n");
return JNI_ERR;
#else
if(tail != NULL) {
size_t length = strlen(tail) + 1;
char *options = NEW_C_HEAP_ARRAY(char, length, mtInternal);
jio_snprintf(options, length, "%s", tail);
add_init_agent("instrument", options, false);
}
#endif // !INCLUDE_JVMTI
// 其他不常用的参数,也就不过多介绍,有兴趣的自行查找资料研究
// -Xnoclassgc
} else if (match_option(option, "-Xnoclassgc", &tail)) {
FLAG_SET_CMDLINE(bool, ClassUnloading, false);
// -Xincgc: i-CMS
} else if (match_option(option, "-Xincgc", &tail)) {
FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, true);
FLAG_SET_CMDLINE(bool, CMSIncrementalMode, true);
// -Xnoincgc: no i-CMS
} else if (match_option(option, "-Xnoincgc", &tail)) {
FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, false);
FLAG_SET_CMDLINE(bool, CMSIncrementalMode, false);
// -Xconcgc
} else if (match_option(option, "-Xconcgc", &tail)) {
FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, true);
// -Xnoconcgc
} else if (match_option(option, "-Xnoconcgc", &tail)) {
FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, false);
// -Xbatch
} else if (match_option(option, "-Xbatch", &tail)) {
FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
// 重点讲解一下后面几个参数:-Xmn -Xms -Xmx -Xss -Xoss
} else if (match_option(option, "-Xmn", &tail)) {
julong long_initial_young_size = 0;
ArgsRange errcode = parse_memory_size(tail, &long_initial_young_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid initial young generation size: %s\n", option->optionString);
describe_range_error(errcode);
return JNI_EINVAL;
}
// MaxNewSize 最大的年轻代大小;newSize 初始的年轻代大小。FLAG_SET_CMDLINE是宏定义,展开细节看`章节8.1.1.3`
FLAG_SET_CMDLINE(uintx, MaxNewSize, (uintx)long_initial_young_size);
FLAG_SET_CMDLINE(uintx, NewSize, (uintx)long_initial_young_size);
// -Xms:最小堆大小
} else if (match_option(option, "-Xms", &tail)) {
julong long_initial_heap_size = 0;
// an initial heap size of 0 means automatically determine
ArgsRange errcode = parse_memory_size(tail, &long_initial_heap_size, 0);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid initial heap size: %s\n", option->optionString);
describe_range_error(errcode);
return JNI_EINVAL;
}
// 设置_min_heap_size为最小堆大小
set_min_heap_size((uintx)long_initial_heap_size);
// 当前最小堆大小和初始化堆大小是相同的,也可以通过-XX:InitialHeapSize参数来设置覆盖,FLAG_SET_CMDLINE是宏定义,展开细节看`章节8.1.1.3`
FLAG_SET_CMDLINE(uintx, InitialHeapSize, (uintx)long_initial_heap_size);
// -Xmx:最大堆内存
} else if (match_option(option, "-Xmx", &tail) || match_option(option, "-XX:MaxHeapSize=", &tail)) {
julong long_max_heap_size = 0;
ArgsRange errcode = parse_memory_size(tail, &long_max_heap_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid maximum heap size: %s\n", option->optionString);
describe_range_error(errcode);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, MaxHeapSize, (uintx)long_max_heap_size);
// Xmaxf
} else if (match_option(option, "-Xmaxf", &tail)) {
char* err;
int maxf = (int)(strtod(tail, &err) * 100);
if (*err != '\0' || *tail == '\0' || maxf < 0 || maxf > 100) {
jio_fprintf(defaultStream::error_stream(),
"Bad max heap free percentage size: %s\n",
option->optionString);
return JNI_EINVAL;
} else {
FLAG_SET_CMDLINE(uintx, MaxHeapFreeRatio, maxf);
}
// Xminf
} else if (match_option(option, "-Xminf", &tail)) {
char* err;
int minf = (int)(strtod(tail, &err) * 100);
if (*err != '\0' || *tail == '\0' || minf < 0 || minf > 100) {
jio_fprintf(defaultStream::error_stream(),
"Bad min heap free percentage size: %s\n",
option->optionString);
return JNI_EINVAL;
} else {
FLAG_SET_CMDLINE(uintx, MinHeapFreeRatio, minf);
}
// -Xss:线程堆栈大小
} else if (match_option(option, "-Xss", &tail)) {
julong long_ThreadStackSize = 0;
ArgsRange errcode = parse_memory_size(tail, &long_ThreadStackSize, 1000);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid thread stack size: %s\n", option->optionString);
describe_range_error(errcode);
return JNI_EINVAL;
}
// Internally track ThreadStackSize in units of 1024 bytes.
FLAG_SET_CMDLINE(intx, ThreadStackSize,
round_to((int)long_ThreadStackSize, K) / K);
// -Xoss
} else if (match_option(option, "-Xoss", &tail)) {
// HotSpot does not have separate native and Java stacks, ignore silently for compatibility
} else if (match_option(option, "-XX:CodeCacheExpansionSize=", &tail)) {
julong long_CodeCacheExpansionSize = 0;
ArgsRange errcode = parse_memory_size(tail, &long_CodeCacheExpansionSize, os::vm_page_size());
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid argument: %s. Must be at least %luK.\n", option->optionString,
os::vm_page_size()/K);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, CodeCacheExpansionSize, (uintx)long_CodeCacheExpansionSize);
} else if (match_option(option, "-Xmaxjitcodesize", &tail) ||
match_option(option, "-XX:ReservedCodeCacheSize=", &tail)) {
julong long_ReservedCodeCacheSize = 0;
ArgsRange errcode = parse_memory_size(tail, &long_ReservedCodeCacheSize, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid maximum code cache size: %s.\n", option->optionString);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, ReservedCodeCacheSize, (uintx)long_ReservedCodeCacheSize);
//-XX:IncreaseFirstTierCompileThresholdAt=
} else if (match_option(option, "-XX:IncreaseFirstTierCompileThresholdAt=", &tail)) {
uintx uint_IncreaseFirstTierCompileThresholdAt = 0;
if (!parse_uintx(tail, &uint_IncreaseFirstTierCompileThresholdAt, 0) || uint_IncreaseFirstTierCompileThresholdAt > 99) {
jio_fprintf(defaultStream::error_stream(),
"Invalid value for IncreaseFirstTierCompileThresholdAt: %s. Should be between 0 and 99.\n",
option->optionString);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, IncreaseFirstTierCompileThresholdAt, (uintx)uint_IncreaseFirstTierCompileThresholdAt);
// -green
} else if (match_option(option, "-green", &tail)) {
jio_fprintf(defaultStream::error_stream(),
"Green threads support not available\n");
return JNI_EINVAL;
// -native
} else if (match_option(option, "-native", &tail)) {
// HotSpot always uses native threads, ignore silently for compatibility
// -Xsqnopause
} else if (match_option(option, "-Xsqnopause", &tail)) {
// EVM option, ignore silently for compatibility
// -Xrs
} else if (match_option(option, "-Xrs", &tail)) {
// Classic/EVM option, new functionality
FLAG_SET_CMDLINE(bool, ReduceSignalUsage, true);
} else if (match_option(option, "-Xusealtsigs", &tail)) {
// change default internal VM signals used - lower case for back compat
FLAG_SET_CMDLINE(bool, UseAltSigs, true);
// -Xoptimize
} else if (match_option(option, "-Xoptimize", &tail)) {
// EVM option, ignore silently for compatibility
// -Xprof
} else if (match_option(option, "-Xprof", &tail)) {
#if INCLUDE_FPROF
_has_profile = true;
#else // INCLUDE_FPROF
jio_fprintf(defaultStream::error_stream(),
"Flat profiling is not supported in this VM.\n");
return JNI_ERR;
#endif // INCLUDE_FPROF
// -Xconcurrentio
} else if (match_option(option, "-Xconcurrentio", &tail)) {
FLAG_SET_CMDLINE(bool, UseLWPSynchronization, true);
FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
FLAG_SET_CMDLINE(intx, DeferThrSuspendLoopCount, 1);
FLAG_SET_CMDLINE(bool, UseTLAB, false);
FLAG_SET_CMDLINE(uintx, NewSizeThreadIncrease, 16 * K); // 20Kb per thread added to new generation
// -Xinternalversion
} else if (match_option(option, "-Xinternalversion", &tail)) {
jio_fprintf(defaultStream::output_stream(), "%s\n",
VM_Version::internal_vm_info_string());
vm_exit(0);
#ifndef PRODUCT
// -Xprintflags
} else if (match_option(option, "-Xprintflags", &tail)) {
CommandLineFlags::printFlags(tty, false);
vm_exit(0);
#endif
// -D
} else if (match_option(option, "-D", &tail)) {
if (CheckEndorsedAndExtDirs) {
if (match_option(option, "-Djava.endorsed.dirs=", &tail)) {
// abort if -Djava.endorsed.dirs is set
jio_fprintf(defaultStream::output_stream(),
"-Djava.endorsed.dirs will not be supported in a future release.\n"
"Refer to JEP 220 for details (http://openjdk.java.net/jeps/220).\n");
return JNI_EINVAL;
}
if (match_option(option, "-Djava.ext.dirs=", &tail)) {
// abort if -Djava.ext.dirs is set
jio_fprintf(defaultStream::output_stream(),
"-Djava.ext.dirs will not be supported in a future release.\n"
"Refer to JEP 220 for details (http://openjdk.java.net/jeps/220).\n");
return JNI_EINVAL;
}
}
if (!add_property(tail)) {
return JNI_ENOMEM;
}
// Out of the box management support
if (match_option(option, "-Dcom.sun.management", &tail)) {
#if INCLUDE_MANAGEMENT
FLAG_SET_CMDLINE(bool, ManagementServer, true);
#else
jio_fprintf(defaultStream::output_stream(),
"-Dcom.sun.management is not supported in this VM.\n");
return JNI_ERR;
#endif
}
// -Xint
} else if (match_option(option, "-Xint", &tail)) {
set_mode_flags(_int);
// -Xmixed
} else if (match_option(option, "-Xmixed", &tail)) {
set_mode_flags(_mixed);
// -Xcomp
} else if (match_option(option, "-Xcomp", &tail)) {
// for testing the compiler; turn off all flags that inhibit compilation
set_mode_flags(_comp);
// -Xshare:dump
} else if (match_option(option, "-Xshare:dump", &tail)) {
FLAG_SET_CMDLINE(bool, DumpSharedSpaces, true);
set_mode_flags(_int); // Prevent compilation, which creates objects
// -Xshare:on
} else if (match_option(option, "-Xshare:on", &tail)) {
FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true);
// -Xshare:auto
} else if (match_option(option, "-Xshare:auto", &tail)) {
FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false);
// -Xshare:off
} else if (match_option(option, "-Xshare:off", &tail)) {
FLAG_SET_CMDLINE(bool, UseSharedSpaces, false);
FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false);
// -Xverify
} else if (match_option(option, "-Xverify", &tail)) {
if (strcmp(tail, ":all") == 0 || strcmp(tail, "") == 0) {
FLAG_SET_CMDLINE(bool, BytecodeVerificationLocal, true);
FLAG_SET_CMDLINE(bool, BytecodeVerificationRemote, true);
} else if (strcmp(tail, ":remote") == 0) {
FLAG_SET_CMDLINE(bool, BytecodeVerificationLocal, false);
FLAG_SET_CMDLINE(bool, BytecodeVerificationRemote, true);
} else if (strcmp(tail, ":none") == 0) {
FLAG_SET_CMDLINE(bool, BytecodeVerificationLocal, false);
FLAG_SET_CMDLINE(bool, BytecodeVerificationRemote, false);
} else if (is_bad_option(option, args->ignoreUnrecognized, "verification")) {
return JNI_EINVAL;
}
// -Xdebug
} else if (match_option(option, "-Xdebug", &tail)) {
// note this flag has been used, then ignore
set_xdebug_mode(true);
// -Xnoagent
} else if (match_option(option, "-Xnoagent", &tail)) {
// For compatibility with classic. HotSpot refuses to load the old style agent.dll.
} else if (match_option(option, "-Xboundthreads", &tail)) {
// Bind user level threads to kernel threads (Solaris only)
FLAG_SET_CMDLINE(bool, UseBoundThreads, true);
} else if (match_option(option, "-Xloggc:", &tail)) {
// Redirect GC output to the file. -Xloggc:<filename>
// ostream_init_log(), when called will use this filename
// to initialize a fileStream.
_gc_log_filename = strdup(tail);
if (!is_filename_valid(_gc_log_filename)) {
jio_fprintf(defaultStream::output_stream(),
"Invalid file name for use with -Xloggc: Filename can only contain the "
"characters [A-Z][a-z][0-9]-_.%%[p|t] but it has been %s\n"
"Note %%p or %%t can only be used once\n", _gc_log_filename);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(bool, PrintGC, true);
FLAG_SET_CMDLINE(bool, PrintGCTimeStamps, true);
// JNI hooks
} else if (match_option(option, "-Xcheck", &tail)) {
if (!strcmp(tail, ":jni")) {
#if !INCLUDE_JNI_CHECK
warning("JNI CHECKING is not supported in this VM");
#else
CheckJNICalls = true;
#endif // INCLUDE_JNI_CHECK
} else if (is_bad_option(option, args->ignoreUnrecognized,
"check")) {
return JNI_EINVAL;
}
} else if (match_option(option, "vfprintf", &tail)) {
_vfprintf_hook = CAST_TO_FN_PTR(vfprintf_hook_t, option->extraInfo);
} else if (match_option(option, "exit", &tail)) {
_exit_hook = CAST_TO_FN_PTR(exit_hook_t, option->extraInfo);
} else if (match_option(option, "abort", &tail)) {
_abort_hook = CAST_TO_FN_PTR(abort_hook_t, option->extraInfo);
} else if (match_option(option, "-XX:+NeverTenure", &tail)) {
// The last option must always win.
FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
FLAG_SET_CMDLINE(bool, NeverTenure, true);
} else if (match_option(option, "-XX:+AlwaysTenure", &tail)) {
// The last option must always win.
FLAG_SET_CMDLINE(bool, NeverTenure, false);
FLAG_SET_CMDLINE(bool, AlwaysTenure, true);
} else if (match_option(option, "-XX:+CMSPermGenSweepingEnabled", &tail) ||
match_option(option, "-XX:-CMSPermGenSweepingEnabled", &tail)) {
jio_fprintf(defaultStream::error_stream(),
"Please use CMSClassUnloadingEnabled in place of "
"CMSPermGenSweepingEnabled in the future\n");
} else if (match_option(option, "-XX:+UseGCTimeLimit", &tail)) {
FLAG_SET_CMDLINE(bool, UseGCOverheadLimit, true);
jio_fprintf(defaultStream::error_stream(),
"Please use -XX:+UseGCOverheadLimit in place of "
"-XX:+UseGCTimeLimit in the future\n");
} else if (match_option(option, "-XX:-UseGCTimeLimit", &tail)) {
FLAG_SET_CMDLINE(bool, UseGCOverheadLimit, false);
jio_fprintf(defaultStream::error_stream(),
"Please use -XX:-UseGCOverheadLimit in place of "
"-XX:-UseGCTimeLimit in the future\n");
// The TLE options are for compatibility with 1.3 and will be
// removed without notice in a future release. These options
// are not to be documented.
} else if (match_option(option, "-XX:MaxTLERatio=", &tail)) {
// No longer used.
} else if (match_option(option, "-XX:+ResizeTLE", &tail)) {
FLAG_SET_CMDLINE(bool, ResizeTLAB, true);
} else if (match_option(option, "-XX:-ResizeTLE", &tail)) {
FLAG_SET_CMDLINE(bool, ResizeTLAB, false);
} else if (match_option(option, "-XX:+PrintTLE", &tail)) {
FLAG_SET_CMDLINE(bool, PrintTLAB, true);
} else if (match_option(option, "-XX:-PrintTLE", &tail)) {
FLAG_SET_CMDLINE(bool, PrintTLAB, false);
} else if (match_option(option, "-XX:TLEFragmentationRatio=", &tail)) {
// No longer used.
} else if (match_option(option, "-XX:TLESize=", &tail)) {
julong long_tlab_size = 0;
ArgsRange errcode = parse_memory_size(tail, &long_tlab_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid TLAB size: %s\n", option->optionString);
describe_range_error(errcode);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, TLABSize, long_tlab_size);
} else if (match_option(option, "-XX:TLEThreadRatio=", &tail)) {
// No longer used.
} else if (match_option(option, "-XX:+UseTLE", &tail)) {
FLAG_SET_CMDLINE(bool, UseTLAB, true);
} else if (match_option(option, "-XX:-UseTLE", &tail)) {
FLAG_SET_CMDLINE(bool, UseTLAB, false);
} else if (match_option(option, "-XX:+DisplayVMOutputToStderr", &tail)) {
FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, false);
FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, true);
} else if (match_option(option, "-XX:+DisplayVMOutputToStdout", &tail)) {
FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, false);
FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, true);
} else if (match_option(option, "-XX:+ErrorFileToStderr", &tail)) {
FLAG_SET_CMDLINE(bool, ErrorFileToStdout, false);
FLAG_SET_CMDLINE(bool, ErrorFileToStderr, true);
} else if (match_option(option, "-XX:+ErrorFileToStdout", &tail)) {
FLAG_SET_CMDLINE(bool, ErrorFileToStderr, false);
FLAG_SET_CMDLINE(bool, ErrorFileToStdout, true);
} else if (match_option(option, "-XX:+ExtendedDTraceProbes", &tail)) {
#if defined(DTRACE_ENABLED)
FLAG_SET_CMDLINE(bool, ExtendedDTraceProbes, true);
FLAG_SET_CMDLINE(bool, DTraceMethodProbes, true);
FLAG_SET_CMDLINE(bool, DTraceAllocProbes, true);
FLAG_SET_CMDLINE(bool, DTraceMonitorProbes, true);
#else // defined(DTRACE_ENABLED)
jio_fprintf(defaultStream::error_stream(),
"ExtendedDTraceProbes flag is not applicable for this configuration\n");
return JNI_EINVAL;
#endif // defined(DTRACE_ENABLED)
#ifdef ASSERT
} else if (match_option(option, "-XX:+FullGCALot", &tail)) {
FLAG_SET_CMDLINE(bool, FullGCALot, true);
// disable scavenge before parallel mark-compact
FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
#endif
} else if (match_option(option, "-XX:CMSParPromoteBlocksToClaim=", &tail)) {
julong cms_blocks_to_claim = (julong)atol(tail);
FLAG_SET_CMDLINE(uintx, CMSParPromoteBlocksToClaim, cms_blocks_to_claim);
jio_fprintf(defaultStream::error_stream(),
"Please use -XX:OldPLABSize in place of "
"-XX:CMSParPromoteBlocksToClaim in the future\n");
} else if (match_option(option, "-XX:ParCMSPromoteBlocksToClaim=", &tail)) {
julong cms_blocks_to_claim = (julong)atol(tail);
FLAG_SET_CMDLINE(uintx, CMSParPromoteBlocksToClaim, cms_blocks_to_claim);
jio_fprintf(defaultStream::error_stream(),
"Please use -XX:OldPLABSize in place of "
"-XX:ParCMSPromoteBlocksToClaim in the future\n");
} else if (match_option(option, "-XX:ParallelGCOldGenAllocBufferSize=", &tail)) {
julong old_plab_size = 0;
ArgsRange errcode = parse_memory_size(tail, &old_plab_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid old PLAB size: %s\n", option->optionString);
describe_range_error(errcode);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, OldPLABSize, old_plab_size);
jio_fprintf(defaultStream::error_stream(),
"Please use -XX:OldPLABSize in place of "
"-XX:ParallelGCOldGenAllocBufferSize in the future\n");
} else if (match_option(option, "-XX:ParallelGCToSpaceAllocBufferSize=", &tail)) {
julong young_plab_size = 0;
ArgsRange errcode = parse_memory_size(tail, &young_plab_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid young PLAB size: %s\n", option->optionString);
describe_range_error(errcode);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, YoungPLABSize, young_plab_size);
jio_fprintf(defaultStream::error_stream(),
"Please use -XX:YoungPLABSize in place of "
"-XX:ParallelGCToSpaceAllocBufferSize in the future\n");
} else if (match_option(option, "-XX:CMSMarkStackSize=", &tail) ||
match_option(option, "-XX:G1MarkStackSize=", &tail)) {
julong stack_size = 0;
ArgsRange errcode = parse_memory_size(tail, &stack_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid mark stack size: %s\n", option->optionString);
describe_range_error(errcode);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, MarkStackSize, stack_size);
} else if (match_option(option, "-XX:CMSMarkStackSizeMax=", &tail)) {
julong max_stack_size = 0;
ArgsRange errcode = parse_memory_size(tail, &max_stack_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid maximum mark stack size: %s\n",
option->optionString);
describe_range_error(errcode);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, MarkStackSizeMax, max_stack_size);
} else if (match_option(option, "-XX:ParallelMarkingThreads=", &tail) ||
match_option(option, "-XX:ParallelCMSThreads=", &tail)) {
uintx conc_threads = 0;
if (!parse_uintx(tail, &conc_threads, 1)) {
jio_fprintf(defaultStream::error_stream(),
"Invalid concurrent threads: %s\n", option->optionString);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, ConcGCThreads, conc_threads);
} else if (match_option(option, "-XX:MaxDirectMemorySize=", &tail)) {
julong max_direct_memory_size = 0;
ArgsRange errcode = parse_memory_size(tail, &max_direct_memory_size, 0);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid maximum direct memory size: %s\n",
option->optionString);
describe_range_error(errcode);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, MaxDirectMemorySize, max_direct_memory_size);
} else if (match_option(option, "-XX:+UseVMInterruptibleIO", &tail)) {
// NOTE! In JDK 9, the UseVMInterruptibleIO flag will completely go
// away and will cause VM initialization failures!
warning("-XX:+UseVMInterruptibleIO is obsolete and will be removed in a future release.");
FLAG_SET_CMDLINE(bool, UseVMInterruptibleIO, true);
#if !INCLUDE_MANAGEMENT
} else if (match_option(option, "-XX:+ManagementServer", &tail)) {
jio_fprintf(defaultStream::error_stream(),
"ManagementServer is not supported in this VM.\n");
return JNI_ERR;
#endif // INCLUDE_MANAGEMENT
#if INCLUDE_JFR
} else if (match_jfr_option(&option)) {
return JNI_EINVAL;
#endif
} else if (match_option(option, "-XX:", &tail)) { // 剩下的-XX:xxxx 格式的都在这里处理,比如元空间大小-XX:MetaspaceSize=N
// Skip -XX:Flags= since that case has already been handled
if (strncmp(tail, "Flags=", strlen("Flags=")) != 0) {
if (!process_argument(tail, args->ignoreUnrecognized, origin)) {
return JNI_EINVAL;
}
}
// Unknown option
} else if (is_bad_option(option, args->ignoreUnrecognized)) {
return JNI_ERR;
}
}
// PrintSharedArchiveAndExit will turn on
// -Xshare:on
// -XX:+TraceClassPaths
if (PrintSharedArchiveAndExit) {
FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true);
FLAG_SET_CMDLINE(bool, TraceClassPaths, true);
}
// Change the default value for flags which have different default values
// when working with older JDKs.
#ifdef LINUX
if (JDK_Version::current().compare_major(6) <= 0 &&
FLAG_IS_DEFAULT(UseLinuxPosixThreadCPUClocks)) {
FLAG_SET_DEFAULT(UseLinuxPosixThreadCPUClocks, false);
}
#endif // LINUX
fix_appclasspath();
return JNI_OK;
}
// 宏展开前
#define FLAG_SET_CMDLINE(type, name, value) (CommandLineFlagsEx::type##AtPut(FLAG_MEMBER_WITH_TYPE(name,type), (type)(value), Flag::COMMAND_LINE))
#define FLAG_MEMBER_WITH_TYPE(flag,type) Flag_##flag##_##type
// 调用宏
FLAG_SET_CMDLINE(uintx, MaxNewSize, (uintx)long_initial_young_size);
FLAG_SET_CMDLINE(uintx, NewSize, (uintx)long_initial_young_size);
// 宏展开后
(CommandLineFlagsEx::uintxAtPut(Flag_MaxNewSize_uintx, (uintx)(value), Flag::COMMAND_LINE))
(CommandLineFlagsEx::uintxAtPut(Flag_NewSize_uintx, (uintx)(value), Flag::COMMAND_LINE))
CommandLineFlagsEx::uintxAtPut函数的实现
这个函数就是把选项参数封装成一个Flag对象,把value值和类型Flag::COMMAND_LINE对应起来
void CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin) {
Flag* faddr = address_of_flag(flag);
guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type");
trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_uintx(), value, origin);
faddr->set_uintx(value);
faddr->set_origin(origin);
}