Java启动参数分为JVM参数(如-Xmx2g、-Dfile.encoding=UTF-8)和程序参数(如--port 8080),前者由JVM解析,后者传入main方法;混用会导致乱码、参数丢失等问题。

Java启动参数分两类:JVM参数和程序参数,别混用
运行Java程序时传入的参数实际被分成两部分:-Xmx2g 这类以 -X、-XX、-D 开头的是JVM参数,由JVM解析并影响内存、GC、系统属性等;而 arg1 arg2 这类不带短横线的才是你程序里 main(String[] args) 接收到的程序参数。常见错误是把 -Dfile.encoding=UTF-8 放在程序参数位置,结果JVM根本读不到,导致乱码。
正确写法示例:
java -Xms512m -Xmx2g -Dlog.level=debug -jar app.jar --port 8080 --env prod
其中 -Xms512m、-Xmx2g、-Dlog.level=debug 是JVM参数;--port 8080 和 --env prod 是程序参数(假设你的应用用的是Spring Boot风格的命令行选项)。
-Xms 和 -Xmx 必须配对设置,且注意单位大小写
-Xms 控制JVM初始堆大小,-Xmx 控制最大堆大小。如果只设 -Xmx 不设 -Xms,JVM会从很小的默认值(如2MB)开始动态扩容,频繁触发GC,尤其在压测或冷启动阶段表现明显。
立即学习“Java免费学习笔记(深入)”;
-
-Xms2g和-Xmx2g设成相等,可避免堆自动伸缩带来的停顿 - 单位必须是
k、m、g(小写),-Xmx2G在某些JVM版本会报错Invalid initial heap size: -Xms2G - 不要写
-Xms=512m—— 等号是错的,正确是-Xms512m - 超过4G建议启用
-XX:+UseG1GC,否则CMS或Parallel GC可能表现不佳
-D 参数用于设置系统属性,但有加载时机限制
-D 设置的键值对最终通过 System.getProperty("key") 读取,但它只在JVM启动早期生效。如果你在程序里先调用了 System.setProperties(...) 或修改了 System.getProperties(),后续再用 -D 设置的值可能被覆盖或忽略。
典型使用场景:
-
-Dfile.encoding=UTF-8:避免读文件/控制台输出乱码(尤其Windows默认GBK) -
-Duser.timezone=GMT+8:防止SimpleDateFormat或java.time默认用系统时区出错 -
-Djava.security.egd=file:/dev/./urandom:加速SecureRandom初始化(Linux容器常见卡顿点)
注意:-D 不能用来传业务配置,比如 -Ddb.url=jdbc:mysql://... —— 这种应交给配置中心或application.yml,否则运维无法动态调整。
IDE里配置参数容易漏掉“程序参数”区域
IntelliJ IDEA 或 Eclipse 的 Run Configuration 中,有两个独立输入框:“VM options”和“Program arguments”。新手常把所有参数都塞进 VM options,结果 args 数组为空,程序逻辑拿不到命令行开关。
排查方法:
- 在
main方法开头加System.out.println(Arrays.toString(args));,确认是否真收到了 - 检查IDE配置页签是否选错(例如误配到 JUnit 配置而非 Application 配置)
- Maven插件运行时(
mvn spring-boot:run),要用-Dspring-boot.run.jvmArguments=...传JVM参数,程序参数则用-Dspring-boot.run.arguments=...
容器环境更需小心:Docker中 java -jar 命令的参数顺序、entrypoint脚本是否意外截断了参数、Kubernetes的 args: 字段是否被YAML解析器拆分——这些地方都容易让 --debug 类参数消失不见。










