承接上一篇

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命令参数的读取处理流程相关推荐

  1. OpenJDK源码赏析之二:java虚拟机启动流程到首函数调用全流程

    承接上一谈 OpenJDK源码赏析之一:漫谈java的历史渊源_星空_AZ的博客-CSDN博客 JAVA从启动到第一个函数执行的发生的流程: WinMain->JLI_Launch->JV ...

  2. OpenJDK源码赏析之四(jli_util中的工具函数)

    上一篇: OpenJDK源码赏析之三:Java命令参数的读取_星空_MAX的博客-CSDN博客 不承接上一篇,这篇单独开始分析jli_util.h(java工具函数)里的一些函数 JLI_MemAll ...

  3. Java虚拟机(JVM源码):编译OpenJDK源码

    为什么要自己编译JDK源码 作为一个搞技术的同学,如果想在技术这条路上走下去,还是多研究些本质性的东西,修炼下内功.尤其是现在JDK都出到10了,如果你没有研究过,还是停留在之前的时代,那么确实说不过 ...

  4. java 官网下载jdk源码_openJDK之如何下载各个版本的openJDK源码

    如果我们需要阅读openJDK的源码,那么需要下载,那么该去哪下载呢? 现在JDK已经发展到版本10了,11已经处于计划中,如果需要特定版本的openJDK,它们的下载链接在哪呢? 1.openJDK ...

  5. jdk下没有java源码_openJDK之如何下载各个版本的openJDK源码

    如果我们需要阅读openJDK的源码,那么需要下载,那么该去哪下载呢? 现在JDK已经发展到版本10了,11已经处于计划中,如果需要特定版本的openJDK,它们的下载链接在哪呢? 1.openJDK ...

  6. 转-OpenJDK源码阅读导航跟编译

    OpenJDK源码阅读导航 OpenJDK源码阅读导航 博客分类: Virtual Machine HotSpot VM Java OpenJDK openjdk 这是链接帖.主体内容都在各链接中.  ...

  7. 走进JVM之一 自己编译openjdk源码

    想要深入了解JVM,就必须了解其实现机制.了解JVM实现的最好方法便是自己动手编译JDK.好了,让我们开始吧! 1.  准备工作 获取OpenJDK源码 本次编译选择的是OpenJDK7u,官方源码包 ...

  8. commons-math3-3.6.1-org.apache.commons.math3.analysis.function-包下的类(三)-中英对照文档及源码赏析

    commons-math3-3.6.1-org.apache.commons.math3.analysis.function-包下的类(三)-中英对照文档及源码赏析 摘要:中英对照文档.源码赏析.or ...

  9. commons-math3-3.6.1-org.apache.commons.math3.analysis.function-包下的类(二)-中英对照文档及源码赏析

    commons-math3-3.6.1-org.apache.commons.math3.analysis.function-包下的类(二)-中英对照文档及源码赏析 摘要:中英对照文档.源码赏析.or ...

最新文章

  1. 自动禁止ssh的root登陆
  2. Codeforces Global Round 8 C. Even Picture 题解[巧妙法构造题]
  3. yield(C# 参考)
  4. bzoj:3110: [Zjoi2013]K大数查询
  5. 如何让U盘支持大于4G的文件
  6. python三大神器===》装饰器
  7. vsftpd虚拟用户和本地用户不能共存的解决方法
  8. css3怎么设置logo,纯CSS3实现的LOGO标志 ABN AMRO CSS3 logo
  9. return view前端怎么获取_Web 前端路由原理解析和功能实现
  10. 通过证书连接服务器的小命令
  11. Lua中的聊天屏蔽敏感词汇
  12. 高中计算机基础知识课件,高中信息技术基础教案
  13. Quartz 是什么?一文带你入坑
  14. php 鼠标 移动 手型,css各种手型集合(css禁止手型)
  15. 利用百度地图api将excel中的经纬度数据可视化
  16. Oracle 安装步骤
  17. 普通定时器输出互补PWM带死区
  18. 我在绑定微信账号时出现了问题,提示该微信已绑定其他账号
  19. Es refresh index
  20. 安装Chrome失败

热门文章

  1. 人工智能原理、算法和实践思维导图
  2. LZW压缩(解压缩)算法详解及源码
  3. Vim 为什么把 HJKL 当作光标键?
  4. 2022年上海落户最快方式!本科2年落户上海!硕士1年落户上海!
  5. windows-运维-12 Windows 防火墙
  6. PIP安装本地离线包whl
  7. reporting php,PHP报错函数error_reporting()怎么用?
  8. 云和大数据,铺就宁夏特色“信息高速路”
  9. 【Java获取国家法定节假日三种工具类其三】
  10. 驰骋督查督办系统说明书