在线上部署Java应用时,可以通过Java虚拟机(JVM)的参数来控制内存的分配和管理。
常见的JVM配置参数
以下是一些常见的JVM内存参数:
- -Xms: 设置JVM的初始堆大小。 重点关注
- -Xmx: 设置JVM的最大堆大小。 重点关注
- -Xmn: 设置年轻代(Young Generation)的大小。 重点关注
- -XX:NewRatio: 设置年轻代和老年代(Old Generation)的大小比例。
- -XX:SurvivorRatio: 设置Eden区与Survivor区的大小比例。
- -XX:PermSize: 设置永久代(Permanent Generation)的初始大小。
- -XX:MaxPermSize: 设置永久代的最大大小(在Java 8及之后版本中已被移除,由元数据空间(Metaspace)替代)。
- -XX:MetaspaceSize: 设置元数据空间的初始大小。 重点关注
- -XX:MaxMetaspaceSize: 设置元数据空间的最大大小。 重点关注
- -XX:InitialRAMPercentage: 设置JVM初始堆内存的占用百分比。
- -XX:MaxRAMPercentage: 设置JVM最大堆内存的占用百分比。
合理分配JVM内存参数取决于多个因素,包括应用程序的性能需求、可用的物理内存、以及预期的并发访问量等。
一些常见的配置建议
以下是一些建议:
-
根据应用需求调整堆大小: 将 -Xms 和 -Xmx 参数设置为相同的值,以避免堆大小动态调整可能带来的性能开销。根据应用程序的内存需求,设置合适的堆大小,同时确保不会导致频繁的垃圾回收。
-
调整年轻代和老年代的比例: 通过调整 -Xmn、-XX:NewRatio 和 -XX:SurvivorRatio 参数来优化垃圾回收性能。通常情况下,年轻代的大小应该足够大,以容纳大部分的对象,从而减少频繁的Full GC。
-
监控和调整永久代或元数据空间大小: 如果应用程序依赖于大量的类加载或动态生成类,需要监控并根据需要调整永久代或元数据空间的大小。
-
考虑使用容器和云平台的资源管理功能: 如果你的应用程序运行在容器环境或云平台上,可以考虑使用平台提供的资源管理功能,如Kubernetes的资源限制和请求,以确保JVM的内存分配不会超出容器的限制。
-
基于监控数据进行优化: 定期监控应用程序的性能指标,包括内存使用、垃圾回收情况等,并根据监控数据进行内存参数的优化调整。
综上所述,合理分配JVM内存参数需要根据具体的应用需求和运行环境进行综合考虑,并根据实际情况进行调整和优化。
配置实践
Xmx即JVM的堆内存最大值,服务运行时还有MaxMetaspaceSize(生产环境默认是512M,测试环境默认是256M)堆外内存的占用、Linux的内核等系统内存的占用,所以Xmx一定要小于套餐内存限制的大小。 套餐为12G
-
-Xmx
:设置JVM最大可用堆内存。建议为套餐内存大小的70%-80%。9G左右 -
-Xms
:设置JVM初始内存大小。建议Xms和Xmx一样大,绝不可以超过Xmx,否则启动报错。 -
-Xmn
:设置年轻代大小。通常建议为Xmx的1/4到1/3,尽量不要超过Xmx的1/2,否则老年代比例过小容易导致频繁Full GC。其大小设置后面会有详细说明【补充:传统化上不管套餐是4G还是8G,Xmn值都是1024M】。Xmn即年轻代的大小,如果垃圾回收器使用:-XX:+UseParallelGC
或者-XX:+UseConcMarkSweepGC
这两种垃圾回收器,Xmn参数才会生效,如果使用-XX:+UseG1GC
,Xmn不会生效,- Xmn尽量不超过Xmx的1/2,是因为老年代空间较小的话,年轻代长周期对象进入老年代以及大对象直接进入老年代,均可能频繁触发full GC,出现GC抖动的现象,会导致cpu使用率飙升,cpu使用受限,服务阻塞,健康检查存活检查不通过,Pod采取自救措施进行重启。
- 如果你的应用程序生成大量的短生命周期的对象,那么可以需要将-Xmn设置得大一些。如果你的应用程序生成的对象的生命周期较长,那么你可能需要将-Xmn设置得小一些
-
-XX:MetaspaceSize
配置主要看代码中是否会有大量的类对象生成,比如是否大量使用非容器控制的CGLIB技术,使用后没有加缓存,也没有清理缓存
基本配置如上,可能还会有调整