AWS EC2 t3.xlarge实例Java11 JVM老年代内存调优配置咨询
Java 11应用在AWS EC2 t3.xlarge实例内存利用问题解答
问题背景
我们在配备16GB内存的AWS EC2 t3.xlarge实例(64位x86_64 GNU/Linux系统)上运行Java 11应用,目前日志输出内存相关错误,且发现JVM仅使用8GB内存,无法充分利用实例的16GB资源。
应用错误日志
ERROR 10:47:09.326 std.err - Memory: 8555069440 of: 34324873216 ERROR 10:47:09.326 std.err - Thread count: 976 ERROR 10:47:09.326 std.err - IO TPI: 6776.744165170557 TPO: 7549.293 IOR: 1.1139999999999999 QSZ: 37 THROTTLE: 0
JVM堆信息(jcmd输出)
通过jcmd 941 GC.heap_info查看PID为941的应用堆信息,可见老年代内存被限制在8GB:
jcmd 941 GC.heap_info 941: par new generation total 306688K, used 215304K [0x00007fb2c8000000, 0x00007fb2dccc0000, 0x00007fb2dccc0000) eden space 272640K, 76% used [0x00007fb2c8000000, 0x00007fb2d4bf7738, 0x00007fb2d8a40000) from space 34048K, 18% used [0x00007fb2d8a40000, 0x00007fb2d908aa60, 0x00007fb2dab80000) to space 34048K, 0% used [0x00007fb2dab80000, 0x00007fb2dab80000, 0x00007fb2dccc0000) concurrent mark-sweep generation total 8047872K, used 2223911K [0x00007fb2dccc0000, 0x00007fb4c8000000, 0x00007fbac8000000) Metaspace used 223752K, capacity 235070K, committed 235164K, reserved 235520K
用户疑问
是否应通过JAVA_OPTS设置老年代内存?例如使用如下配置:
export JAVA_OPTS="-Xms6144m -Xmx6144m -XX:NewSize=256m -XX:MaxNewSize=356m -XX:PermSize=256m -XX:MaxPermSize=356m"
若需要配置,应设置哪些合理的值?
解答
1. 必须调整参数
肯定要调。现在JVM堆内存(含老年代)才8GB,完全没用到16GB实例的一半资源,纯纯浪费。通过JAVA_OPTS改堆参数能让应用吃满硬件性能,解决当前内存限制问题。
但你给的示例配置有俩坑:
- Java 11早就废掉
PermSize/MaxPermSize了,换成MetaspaceSize/MaxMetaspaceSize就行 - 示例里的
Xmx才6GB,比现在的8GB还小,这完全反了,得改
2. 合理参数怎么设?
16GB内存的机器,得给系统、JVM非堆部分留够空间——比如你现在有976个线程,每个线程栈默认1MB,这就占了近1GB;Metaspace现在用了220MB左右,留512MB足够;还有直接内存、GC线程这些零碎开销,总共留4-6GB给这些非堆和系统进程就够,剩下的10-12GB分给堆内存。
核心参数
-Xms和-Xmx:设成一样的,避免堆动态扩容折腾,建议-Xms10g -Xmx10g(或者12g,看你系统其他进程占用情况)
新生代&老年代比例
- 推荐用
-XX:NewRatio=2,意思是新生代占堆的1/3,老年代占2/3。比如10GB堆的话,新生代3.3GB,老年代6.7GB——比你现在8GB老年代合理多了,老年代太大容易导致GC停顿时间变长。 - 要是不想用比例,也可以直接指定新生代大小:
-XX:NewSize=3g -XX:MaxNewSize=3g
Metaspace参数
- 按当前使用量来,设
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m就行,省得JVM动态调整Metaspace大小。
完整配置示例
export JAVA_OPTS="-Xms10g -Xmx10g -XX:NewRatio=2 -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
3. 调完别忘了验证
- 改完参数重启应用,用
jcmd <PID> GC.heap_info看看堆内存分配是不是符合预期 - 最好加上GC日志参数
-Xlog:gc*:file=gc.log,观察GC停顿时间和内存使用情况,要是GC太频繁或者停顿太长,再微调参数 - 另外t3.xlarge是突发性能实例,要是应用一直高负载,得留意CPU Credits够不够,别光盯着内存忽略了CPU的问题
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

