JVM调优基本步骤

本文来说下JVM调优基本步骤


概述

JVM性能优化步骤

在这里插入图片描述


调什么

JVM调优:1、是想调什么,2、能调什么(只能调开放接口的,很多东西不一定开放接口给你调整),综合考虑只有如下两个方面:

  • 内存方面
  • 线程方面

内存方面

内存方面

  • JVM需要的内存总大小。
  • 各块内存分配,新生代、存活区、老年代。
  • 选择合适的垃圾回收算法、控制GC停顿次数和时间。
  • 解决内存泄漏的问题,辅助代码优化。
  • 内存热点:检查哪些对象在系统中数量最大,辅助代码优化。

线程方面

线程方面

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

如何调优

如何调优

  • 监控JVM的状态,主要是内存、线程、代码、I/O几部分。
  • 分析结果,判断是否需要优化。
  • 调整:垃圾回收算法和内存分配,修改并优化代码。
  • 不断的重复监控、分析和调整,直至找到优化的平衡点。

JVM调优的目标

JVM调优的目标

  • GC的时间足够小。
  • GC的次数足够小。
  • 将转移到老年代的对象数量降低到最小。
  • 减少Full GC的执行时间。
  • 发生Full GC的间隔时间足够的长。

常见的调优策略

常见的调优策略

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

JVM调优的思考

JVM调优的思考

  • 多数的Java应用不需要在服务器上进行GC优化。
  • 多数导致GC问题的Java应用,都不是因为参数设置错误,而是代码问题。
  • 在应用上线前,先考虑将机器的JVM参数设置到最优(最合适)。
  • JVM优化是到最后不得已才采用的手段。
  • 在实例使用中,分析JVM情况优化代码比优化JVM本身要多得多。

如下情况通常不用优化:

  • Minor GC执行时间不到50ms。
  • Minor GC执行不频繁,约10秒甚至更差时间才执行一次。
  • Full GC执行时间不到1s。
  • Full GC执行频率不算频繁,不低于10分钟1次。

JVM调优经验

JVM调优经验

  • 要注意32位和64为操作系统的区别,32位操作系统支持的内存理论上最多为2的32次方4G,而64位操作系统理论的寻址能力为2的64次方,内存识别的多少是和计算机cpu的寻址有关。
  • 注意client模式和Server模式的选择。
  • 要想GC的时间小必须要一个更小的堆,而要保证GC次数足够少,又必须要保证一个更大的堆,这两个是有冲突的,只能取其平衡。
  • 针对JVM堆的设置,一般可以通过-Xms -Xmx限定其最小、最大值,为了防止垃圾收集器在最小、最大之间收缩堆而产生额外的时间,通常把最大、最小设置为相同的值。
  • 新生代和老年代将根据默认的比例(1:2)分配内存堆,可以通过调整二者之间的比率NewRadio来调整,也可以通过-XX:newSize -XX:MaxNewSize来设置其绝对大小,同样,为了防止新生的堆收缩,通常会把-XX:newSize -XX:MaxNewSize设置为同样大小。
  • 合理规划新生代和老年代的大小。
  • 如果应用存在大量的临时对象,应该选择更大的新生代;如果存在相对较多的持久对象,老年代应该适当增大。在抉择时应该本着Full GC尽量少的原则,让老年代尽量缓存常用对象,JVM的默认比例1:2也是这个道理。
  • 通过观察应用一段时间,看其在峰值时老年代会占多少内存,在不影响Full GC的前提下,根据实际情况加大新生代,但应该给老年代至少预留1/3的增长空间。
  • 线程堆栈的设置:每个线程默认会开启1M的堆栈,用于存放栈帧、调用参数、局部变量等,对大多数应用而言这个默认值太大了,一般256K就足够了。在内存不变的情况下,减少每个线程的堆栈,可以产生更多的线程。

内存泄漏

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

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

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

堆栈溢出的情况,通常会抛出java.lang.StackOverflowError,一般就是递归调用没退出,或者循环调用导致


调优步骤

重点是调优的过程、方法和思路。内存调整、数据库连接调整、内存泄漏查找等。通过JMC录制JFR飞行记录

  1. 查看CPU的占用率
  2. 内存的分配和使用量
  3. 垃圾收集的执行频率、暂停时间、垃圾收集区域
  4. 文件I/O、套接字I/O,查看远程I/O阻塞时间

一般信息,堆使用量、CPU总体占用率、GC暂停时间是非常重要的三个指标,对于Java应用而言,GC暂停时间是最值得关注的指标。

在这里插入图片描述

通过内存信息,我们可以清晰的看到垃圾收集器的类型,垃圾收集的暂停时间,包括最短暂停时间、平均暂停时间、最长暂停时间,以及更为重要的垃圾收集频率(垃圾收集的周期及STW时长)。

在这里插入图片描述

代码分析是Java性能分析重点,通过代码分析,我们可以清楚的知道系统运行时,哪些类及方法被高频率的调用。

在这里插入图片描述

热点方法,通过查看热点方法调用栈,我们可以清晰的了解到系统的主要计算资源消耗情况。

在这里插入图片描述

通过调用树,我们能以模块化的方式直观的看到系统运行状态。

在这里插入图片描述

通过线程概述报告,我们可以得知CPU占用率的分布(系统占用率、应用程序+JVM占用率)和活动线程数,对于CPU占用率而言,应用程序应该占用99%的计算资源,而活动线程数应该控制在合理范围内(具体看应用)。

在这里插入图片描述

热点线程一栏,详细列出了热点线程的数量及详情,通过详情,我们可以得知线程的执行情况。

在这里插入图片描述

线程争用是解决应用性能最为关键的部分,在应用上线初期,我们可以通过解决线程争用初步实现系统性能的巨大提升。上图中的争用为GC导致,具体是由于使用G1时,设置的GC预期暂停时间过短导致的。

在这里插入图片描述

IO作为系统的基础指标,IO过高会导致系统性能急剧下降,避免过度打印日志和生成大文件可以避免系统IO过高导致的性能问题。

在这里插入图片描述


通过VisualVM查询实时的虚拟机信息

查看监视界面,可以看到cup运行情况、堆的使用情况、类的情况以及线程的动态情况。

在这里插入图片描述

查看线程,可以看到所有的线程的情况,是运行、休眠、等待、驻留、监视等情况。

在这里插入图片描述

也可以点击右上角Dump按钮,将线程的信息导出,其实就是执行的jstack命令

在这里插入图片描述

查看抽样器,抽样器可以对CPU、内存在一段时间内进行抽样,

  • CPU监控:查看热点方法和各个方法占用CPU时间及其比例。
  • 内存监控:每个线程分配内存。

在这里插入图片描述

抽样cpu

在这里插入图片描述

添加插件Visual GC,利用Visual GC分析虚拟机内存区域。

  • 内存大小分情况
  • 主要关注 GC Time长短及间隔
  • 查看是否old Gen,Eden是否存在持续上升

在这里插入图片描述


本文小结

通过JMC录制JFR飞行记录和通过VisualVM监控实时的虚拟机信息,进行调整优化。

针对性的去调整JVM内存、新生代、年代的空间大小、数据库连接池大小、MySQL最大连接数等。

不断的分析和调整,直到找到合适的JVM参数配置,找到最合适的参数,将这些参数应用到所有服务器,并进行后续跟踪。

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值