OpenJDK源码赏析之三:Java命令参数的读取处理流程
承接上一篇
OpenJDK源码赏析之二:java虚拟机启动流程到首函数调用全流程_星空_AZ的博客-CSDN博客
这篇这要解析Java虚拟机创建时候配置读取时候命令行参数的读取过程,这次采取逆向思维分析,从结尾顺藤摸瓜找到源头的方式去找到读取命令行参数的地方,就从下面这个InitializeJVM函数为缺口慢慢展开全流程:
/** Initializes the Java Virtual Machine. Also frees options array when* finished.*/
static jboolean
InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn)
{JavaVMInitArgs args;jint r;memset(&args, 0, sizeof(args));args.version = JNI_VERSION_1_2;args.nOptions = numOptions;args.options = options;args.ignoreUnrecognized = JNI_FALSE;if (JLI_IsTraceLauncher()) {int i = 0;printf("JavaVM args:\n ");printf("version 0x%08lx, ", (long)args.version);printf("ignoreUnrecognized is %s, ",args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE");printf("nOptions is %ld\n", (long)args.nOptions);for (i = 0; i < numOptions; i++)printf(" option[%2d] = '%s'\n",i, args.options[i].optionString);}r = ifn->CreateJavaVM(pvm, (void **)penv, &args);JLI_MemFree(options);return r == JNI_OK;
}
注意到这一函数开始的注释为初始化java虚拟机,并释放列表清单
最后 r = ifn->CreateJavaVM(pvm, (void **)penv, &args);这句为创建虚拟机
后面这句JLI_MemFree(options);就是释放options的内存空间了
那么既然找到释放的地方,那也会有个创建的地方
搜索在java.c找到开头有个地方定义了这个options
为JavaVMOption的结构体,顺着找,在jni.h找到该结构体的定义位置
optionString为设置字段,extraInfo为额外信息
在java.c查找到对JavaVMOption操作的地方,AddOption为在原来的基础上添加设置,下面为其源码:
/** Adds a new VM option with the given given name and value.*/
void
AddOption(char *str, void *info)
{/** Expand options array if needed to accommodate at least one more* VM option.*/if (numOptions >= maxOptions) {if (options == 0) {maxOptions = 4;options = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));} else {JavaVMOption *tmp;maxOptions *= 2;tmp = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));memcpy(tmp, options, numOptions * sizeof(JavaVMOption));JLI_MemFree(options);options = tmp;}}options[numOptions].optionString = str;options[numOptions++].extraInfo = info;if (JLI_StrCCmp(str, "-Xss") == 0) {jlong tmp;if (parse_size(str + 4, &tmp)) {threadStackSize = tmp;}}if (JLI_StrCCmp(str, "-Xmx") == 0) {jlong tmp;if (parse_size(str + 4, &tmp)) {maxHeapSize = tmp;}}if (JLI_StrCCmp(str, "-Xms") == 0) {jlong tmp;if (parse_size(str + 4, &tmp)) {initialHeapSize = tmp;}}
}
该函式为动态扩容函数,一旦要读取的命令行参数数量超过max自动扩容,非常值得分析
这个部分的扩容部分非常值得分析,我加了注释的解析如下:
/** Expand options array if needed to accommodate at least one more* VM option.* 人工翻译:如果需要至少容纳一个或多个参数,会展开选项容纳空间*///当选项数大于最大空间时if (numOptions >= maxOptions) {//如果没有设置options,那么将最大设置变为4,然后分配空间if (options == 0) {maxOptions = 4;options = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));} else {//如果设置了options,将maxOptions扩容为原来的二倍JavaVMOption *tmp;maxOptions *= 2;//先拿中间变量存储分配新大小的一个空间,tmp = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));//用原来的options内容复制到tmp中间变量中/*memcpy(tmp, options, numOptions * sizeof(JavaVMOption))将numOptions个 */JavaVMOption存储空间的options拷贝到tmp,从而完成对numOptions的赋值memcpy(tmp, options, numOptions * sizeof(JavaVMOption));//将原来的空间释放掉JLI_MemFree(options);//将保存过的旧的数据放入新空间中options = tmp;}}
插入:
注意memcpy,C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1,这是个不安全的函数,使用时候一定要多加注意
具体可看我的另外一篇文章:
memcpy函数及其缺陷分析_星空_AZ的博客-CSDN博客
回到正题:
那么接着去查找调用AddOption的地方,看看配置是从哪里进,就在上面的ParseArguments,命令参数语法分析函数,以下为其源码
static jboolean
ParseArguments(int *pargc, char ***pargv,int *pmode, char **pwhat,int *pret, const char *jrepath)
{int argc = *pargc;char **argv = *pargv;edint mode = LM_UNKNOWN;char *arg;*pret = 0;while ((arg = *argv) != 0 && *arg == '-') {argv++; --argc;if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) {ARG_CHECK (argc, ARG_ERROR1, arg);SetClassPath(*argv);mode = LM_CLASS;argv++; --argc;} else if (JLI_StrCmp(arg, "-jar") == 0) {ARG_CHECK (argc, ARG_ERROR2, arg);mode = LM_JAR;} else if (JLI_StrCmp(arg, "-help") == 0 ||JLI_StrCmp(arg, "-h") == 0 ||JLI_StrCmp(arg, "-?") == 0) {printUsage = JNI_TRUE;return JNI_TRUE;} else if (JLI_StrCmp(arg, "-version") == 0) {printVersion = JNI_TRUE;return JNI_TRUE;} else if (JLI_StrCmp(arg, "-showversion") == 0) {showVersion = JNI_TRUE;} else if (JLI_StrCmp(arg, "-X") == 0) {printXUsage = JNI_TRUE;return JNI_TRUE;
/** The following case checks for -XshowSettings OR -XshowSetting:SUBOPT.* In the latter case, any SUBOPT value not recognized will default to "all"*/} else if (JLI_StrCmp(arg, "-XshowSettings") == 0 ||JLI_StrCCmp(arg, "-XshowSettings:") == 0) {showSettings = arg;} else if (JLI_StrCmp(arg, "-Xdiag") == 0) {AddOption("-Dsun.java.launcher.diag=true", NULL);
/** The following case provide backward compatibility with old-style* command line options.*/} else if (JLI_StrCmp(arg, "-fullversion") == 0) {JLI_ReportMessage("%s full version \"%s\"", _launcher_name, GetFullVersion());return JNI_FALSE;} else if (JLI_StrCmp(arg, "-verbosegc") == 0) {AddOption("-verbose:gc", NULL);} else if (JLI_StrCmp(arg, "-t") == 0) {AddOption("-Xt", NULL);} else if (JLI_StrCmp(arg, "-tm") == 0) {AddOption("-Xtm", NULL);} else if (JLI_StrCmp(arg, "-debug") == 0) {AddOption("-Xdebug", NULL);} else if (JLI_StrCmp(arg, "-noclassgc") == 0) {AddOption("-Xnoclassgc", NULL);} else if (JLI_StrCmp(arg, "-Xfuture") == 0) {AddOption("-Xverify:all", NULL);} else if (JLI_StrCmp(arg, "-verify") == 0) {AddOption("-Xverify:all", NULL);} else if (JLI_StrCmp(arg, "-verifyremote") == 0) {AddOption("-Xverify:remote", NULL);} else if (JLI_StrCmp(arg, "-noverify") == 0) {AddOption("-Xverify:none", NULL);} else if (JLI_StrCCmp(arg, "-prof") == 0) {char *p = arg + 5;char *tmp = JLI_MemAlloc(JLI_StrLen(arg) + 50);if (*p) {sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);} else {sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");}AddOption(tmp, NULL);} else if (JLI_StrCCmp(arg, "-ss") == 0 ||JLI_StrCCmp(arg, "-oss") == 0 ||JLI_StrCCmp(arg, "-ms") == 0 ||JLI_StrCCmp(arg, "-mx") == 0) {char *tmp = JLI_MemAlloc(JLI_StrLen(arg) + 6);sprintf(tmp, "-X%s", arg + 1); /* skip '-' */AddOption(tmp, NULL);} else if (JLI_StrCmp(arg, "-checksource") == 0 ||JLI_StrCmp(arg, "-cs") == 0 ||JLI_StrCmp(arg, "-noasyncgc") == 0) {/* No longer supported */JLI_ReportErrorMessage(ARG_WARN, arg);} else if (JLI_StrCCmp(arg, "-version:") == 0 ||JLI_StrCmp(arg, "-no-jre-restrict-search") == 0 ||JLI_StrCmp(arg, "-jre-restrict-search") == 0 ||JLI_StrCCmp(arg, "-splash:") == 0) {; /* Ignore machine independent options already handled */} else if (ProcessPlatformOption(arg)) {; /* Processing of platform dependent options */} else if (RemovableOption(arg)) {; /* Do not pass option to vm. */} else {AddOption(arg, NULL);}}if (--argc >= 0) {*pwhat = *argv++;}if (*pwhat == NULL) {*pret = 1;} else if (mode == LM_UNKNOWN) {/* default to LM_CLASS if -jar and -cp option are* not specified */mode = LM_CLASS;}if (argc >= 0) {*pargc = argc;*pargv = argv;}*pmode = mode;return JNI_TRUE;
}
哈哈,看到平常在命令行输入的-help参数没有
就是在这里读取的,读取了在cmd输入的命令行参数,具体还有很多细节,没分析到位,水平有限谅解一下哈
OpenJDK源码赏析之三:Java命令参数的读取处理流程相关推荐
- OpenJDK源码赏析之二:java虚拟机启动流程到首函数调用全流程
承接上一谈 OpenJDK源码赏析之一:漫谈java的历史渊源_星空_AZ的博客-CSDN博客 JAVA从启动到第一个函数执行的发生的流程: WinMain->JLI_Launch->JV ...
- OpenJDK源码赏析之四(jli_util中的工具函数)
上一篇: OpenJDK源码赏析之三:Java命令参数的读取_星空_MAX的博客-CSDN博客 不承接上一篇,这篇单独开始分析jli_util.h(java工具函数)里的一些函数 JLI_MemAll ...
- Java虚拟机(JVM源码):编译OpenJDK源码
为什么要自己编译JDK源码 作为一个搞技术的同学,如果想在技术这条路上走下去,还是多研究些本质性的东西,修炼下内功.尤其是现在JDK都出到10了,如果你没有研究过,还是停留在之前的时代,那么确实说不过 ...
- java 官网下载jdk源码_openJDK之如何下载各个版本的openJDK源码
如果我们需要阅读openJDK的源码,那么需要下载,那么该去哪下载呢? 现在JDK已经发展到版本10了,11已经处于计划中,如果需要特定版本的openJDK,它们的下载链接在哪呢? 1.openJDK ...
- jdk下没有java源码_openJDK之如何下载各个版本的openJDK源码
如果我们需要阅读openJDK的源码,那么需要下载,那么该去哪下载呢? 现在JDK已经发展到版本10了,11已经处于计划中,如果需要特定版本的openJDK,它们的下载链接在哪呢? 1.openJDK ...
- 转-OpenJDK源码阅读导航跟编译
OpenJDK源码阅读导航 OpenJDK源码阅读导航 博客分类: Virtual Machine HotSpot VM Java OpenJDK openjdk 这是链接帖.主体内容都在各链接中. ...
- 走进JVM之一 自己编译openjdk源码
想要深入了解JVM,就必须了解其实现机制.了解JVM实现的最好方法便是自己动手编译JDK.好了,让我们开始吧! 1. 准备工作 获取OpenJDK源码 本次编译选择的是OpenJDK7u,官方源码包 ...
- commons-math3-3.6.1-org.apache.commons.math3.analysis.function-包下的类(三)-中英对照文档及源码赏析
commons-math3-3.6.1-org.apache.commons.math3.analysis.function-包下的类(三)-中英对照文档及源码赏析 摘要:中英对照文档.源码赏析.or ...
- commons-math3-3.6.1-org.apache.commons.math3.analysis.function-包下的类(二)-中英对照文档及源码赏析
commons-math3-3.6.1-org.apache.commons.math3.analysis.function-包下的类(二)-中英对照文档及源码赏析 摘要:中英对照文档.源码赏析.or ...
最新文章
- 自动禁止ssh的root登陆
- Codeforces Global Round 8 C. Even Picture 题解[巧妙法构造题]
- yield(C# 参考)
- bzoj:3110: [Zjoi2013]K大数查询
- 如何让U盘支持大于4G的文件
- python三大神器===》装饰器
- vsftpd虚拟用户和本地用户不能共存的解决方法
- css3怎么设置logo,纯CSS3实现的LOGO标志 ABN AMRO CSS3 logo
- return view前端怎么获取_Web 前端路由原理解析和功能实现
- 通过证书连接服务器的小命令
- Lua中的聊天屏蔽敏感词汇
- 高中计算机基础知识课件,高中信息技术基础教案
- Quartz 是什么?一文带你入坑
- php 鼠标 移动 手型,css各种手型集合(css禁止手型)
- 利用百度地图api将excel中的经纬度数据可视化
- Oracle 安装步骤
- 普通定时器输出互补PWM带死区
- 我在绑定微信账号时出现了问题,提示该微信已绑定其他账号
- Es refresh index
- 安装Chrome失败