背景
项目使用阿里云流水线+docker发布。
目前配置如下:
# dockerfile 片段如下
FROM openjdk:8u322-jdk-bullseye
ENV LANG="C.UTF-8"
ENV LC_ALL="C.UTF-8"
ENV TZ=Asia/Shanghai
ENTRYPOINT ["java", "-Dfile.encoding=UTF-8", "-Dsun.jnu.encoding=UTF-8", "-Dcom.sun.jndi.rmi.object.trustURLCodebase=false", "-Dcom.sun.jndi.cosnaming.object.trustURLCodebase=false", "-jar", "/data/app/test_app-8003.jar"]
CMD ["--spring.profiles.active=prod"]
EXPOSE 8003# docker run 片段如下
docker run --memory=1150m --memory-swap=1650m -e JAVA_OPTS="-Xmx512m -Xms256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/dump/memoryError.dump" --name test_app -p 8003:8003 -d $image --spring.profiles.active=test一直以为JAVA_OPTS的参数会生效,实际并未如此。
验证配置未生效
查看容器占用内存: 容器总内存(JVM + 非 JVM)
[root@iZbp14zjgpcsh546yo8puxZ log]# docker stats --no-stream test_app
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
377443d4339d test_app 0.72% 544MiB / 1.123GiB 47.30% 346kB / 711kB 0B / 24.6kB 103查看 JVM 真实使用的内存
[root@iZbp14zjgpcsh546yo8puxZ log]# docker exec -it test_app bash
root@377443d4339d:/data/app# ps ww -o pid,rss,command -C java
PID RSS COMMAND
1 564532 java -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Dcom.sun.jndi.rmi.object.trustURLCodebase=false -Dcom.sun.jndi.cosnaming.object.trustURLCodebase=false -jar /data/app/test_app-8003.jar --spring.profiles.active=testrss:常驻内存(KB)更接近 JVM 实际吃掉的内存
当前 JVM 实际占用物理内存 ≈ 552MB
这已经包括了:
- Java 堆
- Metaspace
- 线程栈
- Direct Memory
- JVM 自身开销
验证容器内 JVM 参数
注意:MaxHeapSize 就是 -Xmx 的内部表示。两者等价。
jcmd 1 VM.flags
[root@iZbp14zjgpcsh546yo8puxZ log]# docker exec -it test_app bash
root@377443d4339d:/data/app# jps
1 test_app-8003.jar
159 Jps
root@377443d4339d:/data/app# jinfo -flag MaxHeapSize 1
-XX:MaxHeapSize=301989888
root@377443d4339d:/data/app# jinfo -flag InitialHeapSize 1
-XX:InitialHeapSize=18874368
root@377443d4339d:/data/app# jinfo -flag MetaspaceSize 1
-XX:MetaspaceSize=21807104
root@377443d4339d:/data/app# jinfo -flag MaxMetaspaceSize 1
-XX:MaxMetaspaceSize=18446744073709547520MaxHeapSize 301989888 B ≈ 288 MB
InitialHeapSize 18874368 B ≈ 18 MB
MetaspaceSize 21807104 B ≈ 20 MB
MaxMetaspaceSize 18446744073709547520 B ≈ 17592186044415 MB ≈ 17179869183 GB (远超物理内存,其实这是 JVM 的默认行为:表示“无上限”。)
原因是docker run命令启动的springboot应用并不会自动读取JAVA_OPTS中的参数配置。
修改并再次验证
把 JAVA_OPTS 修改为 JAVA_TOOL_OPTIONS 即可。
| 环境变量 | 生效机制 | 你的情况 |
|---|---|---|
JAVA_OPTS |
Spring Boot 启动脚本会读取(非标准 JVM) | 容器里 java 命令直接执行不读取 |
JAVA_TOOL_OPTIONS |
JVM 标准机制,所有 java 命令都会自动带上 | 目前没设置,所以 env 看不到 |
JAVA_TOOL_OPTIONS是什么?
JAVA_TOOL_OPTIONS 用来 在 JVM 启动前自动追加参数,无论你怎么调用 java,都会生效。
- 全局生效:对容器里所有 java 进程生效。在 JDK 6 时代就已经存在。
- 优先级:命令行参数会覆盖环境变量
- Spring Boot / 官方镜像都支持:镜像里的 ENTRYPOINT [“java”, “-jar”, “xxx.jar”] 也能生效
- 支持jdk8、jdk11、jdk17、jdk21。(未测试jdk6/jdk7)。后续换 JDK 版本不用改 ENTRYPOINT
验证容器内 JVM 参数
[root@iZbp14zjgpcsh546yo8puxZ log]# docker exec -it test_app bash
root@e7411aa3b513:/data/app# jps
Picked up JAVA_TOOL_OPTIONS: -Xmx512m -Xms256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/dump/memoryError.dump
1 st-remit-portal-8003.jar
122 Jps
root@e7411aa3b513:/data/app# jinfo -flag MaxHeapSize 1
Picked up JAVA_TOOL_OPTIONS: -Xmx512m -Xms256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/dump/memoryError.dump
-XX:MaxHeapSize=536870912
root@e7411aa3b513:/data/app# jinfo -flag InitialHeapSize 1
Picked up JAVA_TOOL_OPTIONS: -Xmx512m -Xms256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/dump/memoryError.dump
-XX:InitialHeapSize=268435456
root@e7411aa3b513:/data/app# jinfo -flag MetaspaceSize 1
Picked up JAVA_TOOL_OPTIONS: -Xmx512m -Xms256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/dump/memoryError.dump
-XX:MetaspaceSize=134217728
root@e7411aa3b513:/data/app# jinfo -flag MaxMetaspaceSize 1
Picked up JAVA_TOOL_OPTIONS: -Xmx512m -Xms256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/dump/memoryError.dump
-XX:MaxMetaspaceSize=268435456MaxHeapSize 536870912 B ≈ 512 MB
InitialHeapSize 268435456 B ≈ 256 MB
MetaspaceSize 134217728 B ≈ 128 MB
MaxMetaspaceSize 268435456 B ≈ 256 MB
和启动参数完全对的上。
参考网站
在线文件大小(bit,bytes,KB,MB,GB,TB)转换换算-BeJSON.com
结论
至此,修复一个4年来从未生效的jvm参数。
作者:张三 创建时间:2025-12-18 09:33
最后编辑:张三 更新时间:2026-01-14 17:39
最后编辑:张三 更新时间:2026-01-14 17:39