09-JVM调优

nobility 发布于 2021-07-19 2868 次阅读


JVM调优

JVM调优步骤

  1. 监控JVM的状态:内存、线程、代码、I/O
  2. 分析结果,判断是否需要优化
  3. 调整垃圾回收算法或进行代码层面的优化
  4. 不断重复上述步骤,直到找到优化的平衡点

内存调优

  • 调整JVM内存总大小,以及各块内存分配(新生代、老年代、存活区),将转移到老年代的对象数量降低到最小
  • 热点内存:检查哪些对象在系统中数量过大,辅助代码优化减少对象的数量
  • 内存泄漏:辅助代码优化
内存泄漏

内存泄漏导致系统崩溃的一些现象如下:

  • 每次垃圾回收时间越来越长,FullGC时间也延长到好几秒
  • FullGC的次数越来越多,最频繁时间间隔不到1分钟
  • 老年代内存越来越大,并且每次FullGC后老年代内存没有被释放
  • 老年代堆空间被占满

出现内存泄漏现象的解决方式:一般就根据垃圾回收前后情况对比,同时更加对象引用情况分析,辅助去查泄漏点

GC调优

选择合适的垃圾回收算法,控制GC的停顿次数和时间

  • 单次GC的时间足够小,GC的次数足够少
  • 减少FullGC的执行时间,FullGC的间隔足够长

线程调优

  • 死锁检测:辅助代码优化
  • Dump线程详细信息:查看线程内部运行情况,查找竞争线程,辅助代码优化
  • CPU热点:检测系统哪些方法占用了大量CPU时间,辅助代码优化

JVM调优策略

在应用上线之前,先考虑将服务器的JVM的参数设置到最合适(内存调优),多数Java应用无需在服务器上进行GC调优,多数导致GC问题的Java应用是代码问题,所以万不得已无需JVM调优,而是通过监控JVM运行情况优化代码即可

  • 减少创建对象的数量
  • 减少使用全局变量和大对象
  • 调整新生代和老年代的大小到最合适
  • 选择合适的GC收集器,并设置合理的参数

若出现以下情况就不再建议进行JVM调优了

  • MinorGC执行时间不到50ms
  • MinorGC执行时间间隔10s左右
  • FullGC执行时间不到1s
  • FullGC执行时间间隔10分钟左右

JVM调优经验

  • 注意服务器32位和64位的区别,通常32位仅支持2-3g左右内存
  • 注意JVM的client模式和server模式的选择,通过JAVA_HOME/jre/lib/amd64/jvm.cfg配置文件进行模式切换,首先要确认JDK支持哪一种或两种模式,查看JAVA_HOME/jre/bin目录下是否存在client或server目录,32位的JDK一般都支持server和client两种模式,而64位的虚拟机只支持server模式,没有client目录
  • 要想GC时间小就不行要更小的堆,而保证GC次数足够少,又要保证更大的堆,两者存在冲突,只能取其平衡
  • 针对JVM堆的设置,一般使用-Xms-Xmx限定其最小值和最大值,为了防止垃圾收集器在最小、最大之间收缩堆而产生额外时间,通常将这两个值设置为相同
  • 新生代和老年代将根据默认比例(1:2)分配堆内存,可通过调整两者之间的比例-XX:NewRatio参数进行调整,也可以通过-XX:newSize-XX:MaxNewSize来调整绝对大小,同样为了防止堆收缩,通常将这两个参数设置为相同
  • 合理设置新生代和老年代的大小,若应用存在大量的临时对象,应该选择更大的新生代,若应用存在较多的持久对象,应该选择更大的老年代,在选择时应该本着FullGC尽量少的原则,让老年代尽量缓存常用对象,JVM默认比例是1:2也是这个道理
  • 在增大新生代时间,也需要至少为老年代预留1/3的增长空间
  • 每个线程默认开启会开启1MB的堆栈空间,用于存放栈帧、调用参数、局部变量等,对大多数应用而言,该默认值太大了,一般使用128KB、256KB足以(使用-Xss参数调整堆栈空间),若出现栈溢出抛出java.lang.StackOverflowError异常,一般都是递归调用没有退出或循环调用造成的,在内存不变的情况下,减少线程堆栈,可产生更多的线程
此作者没有提供个人介绍
最后更新于 2021-07-19