在 nexus-public 项目中,使用了脚本将多个项目进行文件的打包处理,在启动过程中发现少了配置参数,便难以启动,于是顺便做了一个笔记如下:
在 Java 中,命令行参数 -D 用于设置 系统属性(System Properties),其解析和处理由 Java 虚拟机(JVM)自身在启动时直接完成,而不是由 Java 标准库或应用程序代码处理。以下是详细解析:
1. -D 参数的作用
通过 -D 定义的参数会被 JVM 解析为 系统属性,格式为:
java -D<key>=<value> -jar your-app.jar
例如:
java -Dserver.port=8080 -Dlogging.level.root=INFO -jar app.jar
这些属性会存储在 JVM 的全局系统属性表中,应用程序可以通过 System.getProperty() 访问:
String port = System.getProperty("server.port"); // 返回 "8080"
2. -D 参数的解析过程
阶段 1:JVM 启动时解析
- 责任方:JVM 的本地代码(C/C++ 实现)。
- 触发时机:在 JVM 初始化阶段解析命令行参数。
- 解析逻辑:
- JVM 遍历所有命令行参数。
- 当发现以
-D开头的参数时,提取其后的<key>=<value>对。 - 将键值对存入 JVM 内部的系统属性表(
System Properties)。
阶段 2:Java 程序访问
- Java 接口:通过
System.getProperty()或System.getProperties()访问。 - 底层实现:JVM 通过本地方法(Native Method)从系统属性表中读取值。
3. 关键代码位置(JVM 源码)
虽然 JVM 的具体实现因版本和厂商(如 OpenJDK、Oracle JDK)而异,但核心逻辑在以下文件中:
- OpenJDK 源码:
- 文件路径:
src/hotspot/share/runtime/arguments.cpp - 函数:
Arguments::parse_each_vm_init_arg() - 代码片段:
if (match_option(option, "-D", &tail)) { // 解析 -Dkey=value JavaVMOption option; option.optionString = create_string_value(tail); add_property(option); // 将属性添加到系统属性表 }
- 文件路径:
4. 系统属性与程序交互
Java 代码访问系统属性
// 获取单个属性
String value = System.getProperty("key");
// 获取所有属性
Properties props = System.getProperties();
props.list(System.out);
覆盖系统属性
- 启动时覆盖:
java -Dkey=new_value -jar app.jar - 运行时覆盖(不推荐,需安全权限):
System.setProperty("key", "new_value");
5. 与其他参数的区别
| 参数类型 | 示例 | 解析方 | 用途 |
|---|---|---|---|
| JVM 标准参数 | -Xmx1024m | JVM 自身 | 控制 JVM 行为(如内存大小) |
-D 系统属性 | -Dconfig.file=app.properties | JVM 自身 | 传递应用程序配置 |
| 程序自定义参数 | --port=8080 | 应用程序自行解析 | 业务逻辑参数 |
6. 常见问题
Q1:为什么 -D 参数在程序启动后才能访问?
- 因为 JVM 在启动时才会解析命令行参数并初始化系统属性表,程序启动后属性表已固定。
Q2:能否在运行时动态添加 -D 参数?
- 不能。系统属性在 JVM 启动后不可修改(除非通过
System.setProperty(),但受安全策略限制)。
Q3:-D 参数和环境变量(Environment Variables)的区别?
- 系统属性:由 JVM 管理,通过
System.getProperty()访问。 - 环境变量:由操作系统管理,通过
System.getenv()访问。
总结
-D参数由 JVM 直接解析,将键值对存入系统属性表。- 系统属性通过
System.getProperty()访问,是 Java 程序配置的常用手段。 - 底层实现依赖 JVM 的本地代码(C/C++),而非 Java 标准库。
16万+

被折叠的 条评论
为什么被折叠?



