Java应用启动时,main方法的args参数来自java命令中-jar选项之后的参数;必须严格置于-jar JAR文件后、不可夹在JVM参数中,Spring Boot会自动解析这些--开头的参数并注入Environment。

Java应用启动时,main 方法的 args 从哪来?
容器里跑的 Java 应用,业务参数(比如 --spring.profiles.active=prod、--server.port=9001)最终会落到 main(String[] args) 的 args 数组里。关键在于:这些参数必须作为 **java 命令的后续参数** 传入,且必须在 -jar 指定的 JAR 文件之后、不能夹在 JVM 参数中间。
- ✅ 正确顺序:
java -Xmx512m -jar app.jar --spring.profiles.active=prod→args是["--spring.profiles.active=prod"] - ❌ 错误顺序:
java -Xmx512m --spring.profiles.active=prod -jar app.jar→ JVM 报错:无法识别的选项 - ❌ 错误顺序:
java -Xmx512m -jar app.jar -Dspring.profiles.active=prod→-D被当成系统属性传给 JVM,但不会进args;Spring Boot 也收不到这个 profile
Docker 中用 CMD 传业务参数的写法
如果业务参数固定,直接写死在 CMD 最稳妥。注意必须用 shell 形式(带引号的字符串),否则变量或空格会出问题:
CMD ["java", "-Xmx512m", "-jar", "/app.jar", "--spring.profiles.active=prod", "--server.port=8080"]
或者用 shell 形式支持环境变量展开(但要小心 shell 注入):
ENV SPRING_PROFILES=prod CMD java -Xmx512m -jar /app.jar --spring.profiles.active=$SPRING_PROFILES
- 用 JSON 数组格式(
["java", "..."])时,$VAR不会自动展开,必须用 shell 形式 - 若参数含空格或特殊字符(如
--logging.level.root=DEBUG),务必用双引号包裹整个 CMD 字符串 - Spring Boot 应用推荐把业务参数放在
-jar后面,它会自动解析并注入到Environment
运行时通过 docker run -e 动态传参?不行,得换方式
docker run -e 只能设环境变量,不能直接塞进 java 命令行参数。想动态传业务参数,有三个实际可用路径:
- 改用启动脚本:在镜像里放一个
start.sh,CMD ["./start.sh"],脚本里拼接java ... /app.jar $@,然后docker run myapp --spring.profiles.active=dev就能透传 - 用
ENTRYPOINT+CMD组合:定义ENTRYPOINT ["java", "-Xmx512m", "-jar", "/app.jar"],再用CMD ["--spring.profiles.active=prod"],这样docker run后面加的参数会自动追到 CMD 后面 - 依赖 Spring Boot 的外部配置:把参数写进
application-prod.yml,挂载进容器,靠--spring.profiles.active触发加载,不走命令行
Spring Boot 的 -- 分隔符容易被忽略
当你要混用 JVM 参数、系统属性(-D)和 Spring Boot 参数时,必须用 -- 显式分隔:
java -Xmx512m -Duser.timezone=GMT+8 --spring.profiles.active=prod -jar app.jar --server.port=9001
上面这行是错的 —— --spring.profiles.active=prod 在 -jar 前,会被 JVM 当成非法选项。正确写法是:
java -Xmx512m -Duser.timezone=GMT+8 -jar app.jar --spring.profiles.active=prod --server.port=9001
注意:-D 属于 JVM 级别,必须在 -jar 前;而所有以 -- 开头的、Spring Boot 能识别的参数,必须在 -jar 后。这个边界一旦错位,要么启动失败,要么参数静默失效。


















