jvm调优

1、jvm问题

1.1 性能监控

  • GC 频繁
  • cpu load过高
  • OOM
  • 内存泄漏
  • 死锁
  • 程序响应时间较长

1.2 线上常见问题

  • 内存泄漏
    • 堆内存使用过多而没有释放,导致堆内存逐渐减少。

      • 过多的对象,而没有释放,导致对象的数量不断增加,最终导致堆内存逐渐减少。

      • 使用了过多的字符串,而没有释放,导致字符串的数量不断增加,最终导致堆内存逐渐减少。

      • 程序没有正确地释放缓存中的数据,就可能会导致缓存中的数据量逐渐增加,最终导致堆内存逐渐减少,最终导致程序崩溃或性能下降

    • 栈内存使用过多而没有释放,导致栈内存逐渐减少,最终导致程序崩溃或性能下降。

      • 使用了过多的局部变量,而没有释放,导致局部变量的数量不断增加,最终导致栈内存逐渐减少。

      • 使用了过多的递归调用,而没有释放,导致递归调用层次不断增加,最终导致栈内存逐渐减少。

  • CPU占用高
    • 内存泄漏或资源竞争:导致JVM不频繁进行FullGC尝试释放内存空间,最终导致CPU占用率过高。
    • 线程死锁:导致JVM无法释放资源,最终导致CPU占用率过高。
    • 程序的代码逻辑问题:导致JVM执行过程中出现大量的计算和运算,最终导致CPU占用率过高。
    • 网络问题或资源问题,导致JVM无法正常运行,最终导致CPU占用率过高。
    • 程序的并发量过高,导致JVM无法正常处理,最终导致CPU占用率过高。
  • 程序崩溃:程序在执行过程中发生异常,导致程序崩溃。

  • 性能问题:程序执行时间过长,导致响应时间变慢,影响用户体验。

  • 兼容性问题:程序在不同的操作系统或硬件平台上运行时出现兼容性问题。

  • 安全问题:程序存在安全漏洞,导致数据泄露或被攻击。

  • 网络问题:程序在执行过程中出现网络问题,导致数据传输失败或程序无法正常运行。

1.3 GC分类

  • 部分收集(Partial GC):不是完整收集整个Java堆的垃圾收集。其中又分为:
  • 新生代收集(Minor GC / Young GC):只是新生代(Eden / S0, S1)的垃圾收集
  • 老年代收集(Major GC / Old GC):只是老年代的垃圾收集。目前,只有CMS GC会有单独收集老年代的行为。注意,很多时候Major GC会和Full GC混淆使用,需要具体分辨是老年代回收还是整堆回收。
  • 混合收集(Mixed GC):收集整个新生代以及部分老年代的垃圾收集。目前,只有G1 GC会有这种行为
  • 整堆收集(Full GC):收集整个java堆和方法区的垃圾收集。

1.4 GC性能指标

  • 吞吐量:吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间)。
    • 假设虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。
    • 垃圾回收时间越少,吞吐量越高;
  • 暂停时间:STW的时间;
    • Stop-The-World:GC在后台自动发起和自动完成的,在用户不可见的情况下,把用户正常的工作线程全部停掉,即GC停顿,会带给用户不良的体验;
    • 为什么要Stop-The-World?

      • 可达性分析的时候为了确保快照的一致性,需要对整个系统进行冻结,不可以出现分析过程中对象引用关系还在不断变化的情况,也就是Stop-The-World。

      • Stop-The-World是导致GC卡顿的重要原因之一。

    • 举个例子:你在做家务,正在计算家里有多少垃圾的时候,是不能允许别人在这时候清理或者增加垃圾的,否则你的计算将毫无意义。所以在这个时候,你需要把家里的人都关在门外,等你计算好垃圾的数量之后才能让他们进来。

  • 内存占用:Java堆所占的大小。

        以上三点构成不可能三角,即一款垃圾回收器不可能同时满足三点。随着硬件水平的提升,内存占用不再是我们关注的重点,评估垃圾回收器性能时,重点关注吞吐量和暂停时间。吞吐量和暂停时间是相互矛盾的,目前我们追求的效果是:在最大吞吐量优先的情况下,减小暂停时间。

2、原因定位-GC分析工具

工具

分析日志工具

打印GC日志,通过下面工具分析

Universal JVM GC analyzer - Java Garbage collection log analysis made easy

dump出堆文件

使用内存分析工具分析文件:jconsole/ jvisualvm / jprofiler / MAT

实时查看JVM状态

使用阿里Arthas,或jconsole,JVisualVM来实时查看JVM状态

jstack查看堆栈信息

jdk命令使用场景_%cpu(s): 97.8 us,_xixingzhe2的博客-CSDN博客

其他

jdk命令解决CPU占用高

jdk命令使用场景_%cpu(s): 97.8 us,_xixingzhe2的博客-CSDN博客

线上cpu排查_xixingzhe2的博客-CSDN博客

工具分析-内存溢出

jvm 内存泄漏和内存溢出_jvm outofmemory_xixingzhe2的博客-CSDN博客

arthas使用

arthas使用_arthas direct_xixingzhe2的博客-CSDN博客

参数配置

https://blog.csdn.net/xixingzhe2/article/details/122215856

3、性能调优

  • 适当增加内存,根据业务背景选择垃圾回收器
  • 优化代码,控制内存使用
  • 增加机器,分散节点压力
  • 合理设置线程池线程数量
  • 使用中间件提高程序效率,比如缓存,消息队列等

4、jvm配置

4.1 内存区域大小

        首先要调整的,就是各个分区的大小,不过这也要分垃圾回收器,我们仅看一下一些全局的参数。

  • -XX:+UseG1GC 首先,要指定JVM使用的垃圾回收器。尽量不要靠默认值去保证,要显式的指定一个。
  • -Xmx 设置堆的最大值,一般为操作系统的2/3大小。
  • -Xms 设置堆的初始值,一般设置成和Xmx一样的大小来避免动态扩容。
  • -Xmn 年轻代大小,默认新生代占堆大小的1/3。高并发快消亡场景可适当加大这个区域。对半,或者更多,都是可以的。但是在G1下,就不用再设置这个值了,它会自动调整。
  • -XX:MaxMetaspaceSize 限制元空间的大小,一般256M足够。这一般和初始大小**-XX:MetaspaceSize设置成一样的。
  • -XX:MaxDirectMemorySize 设置直接内存的最大值,限制通过DirectByteBuffer申请的内存。
  • -XX:ReservedCodeCacheSize 设置JIT编译后的代码存放区大小,如果观察到这个值有限制,可以适当调大,一般够用。
  • -Xss 设置栈的大小,默认为1M,已经足够用了。

4.2 内存调优

        下面的参数一般默认即可,不需要修改。

  • -XX:+AlwaysPreTouch 启动时就把参数里说好了的内存全部初始化,启动时间会慢一些,但运行速度会增加。
  • -XX:SurvivorRatio 默认值为8。表示伊甸区和幸存区的比例。
  • -XX:MaxTenuringThreshold 这个值在CMS下默认为6,G1下默认为15。这个值和我们前面提到的对象提升有关,改动效果会比较明显。对象的年龄分布可以使用-XX:+PrintTenuringDistribution**打印,如果后面几代的大小总是差不多,证明过了某个年龄后的对象总能晋升到老生代,就可以把晋升阈值设小。
  • PretenureSizeThreshold 超过一定大小的对象,将直接在老年代分配。不过这个参数用的不是很多。

4.3 垃圾回收器优化

G1垃圾回收器

  • -XX:MaxGCPauseMillis 设置目标停顿时间,G1会尽力达成。
  • -XX:G1HeapRegionSize 设置小堆区大小。这个值为2的次幂,不要太大,也不要太小。如果是在不知道如何设置,保持默认。
  • -XX:InitiatingHeapOccupancyPercent 当整个堆内存使用达到一定比例(默认是45%),并发标记阶段就会被启动。
  • -XX:ConcGCThreads 并发垃圾收集器使用的线程数量。默认值随JVM运行的平台不同而不同。不建议修改。

4.4 GC日志

  • -XX:+PrintGCDateStamps:打印 GC 发生的时间戳。
  • -XX:+PrintTenuringDistribution:打印 GC 发生时的代龄信息。
  • -XX:+PrintGCApplicationStoppedTime:打印 GC 停顿时长
  • -XX:+PrintGCApplicationConcurrentTime:打印 GC 间隔的服务运行时长
  • -XX:+PrintGCDetails:打印 GC 详情,包括 GC 前/内存等。
  • -Xloggc:…/gclogs/gc.log.date:指定 GC log 的路径

参考:

https://www.toutiao.com/article/7266358530192835124

SpringBoot 性能优化_springboot调优_liuec1002的博客-CSDN博客

你可能感兴趣的:(jvm)