《深入理解Java虚拟机》(六) 调优策略 -- 笔记

@

一、操作文档类功能,大量大对象直接进入老年代

问题现象

  • 操作文档类功能,大量大对象直接进入老年代,没有在Minor GC时被清理,导致老年代迅速消耗殆尽频繁进行Full GC,在服务器内存较大的情况下,Full GC会造成长时间停顿。

解决方法

通过单一Java虚拟机管理大量的内存

  • 控制Full GC 频率,完善代码逻辑,尽量使对象都满足朝生夕灭的原则,维持老年代的稳定;
  • 使用增量回收模式的垃圾收集器,例如G1;
  • 由于指针膨胀和数据类型对齐补白导致相同程序,在64位虚拟机中消耗的内存大于32位虚拟机中消耗的内存,可以开启压缩指针功能。

同一台服务器上部署若干Java虚拟机

使用逻辑集群来使用硬件资源,同一个程序在同一台服务器上使用不同端口号启动多个进程,然后搭建一个负载均衡服务器,以反向代理的方式来分配访问请求(不考虑高可用性需求,使用无Session复制的亲和式集群,均衡器固定将一个用户请求固定分配到一个固定的集群节点);
可能产生的问题:

  • 磁盘资源竞争导致I/O异常;
  • 很难高效利用资源;
  • 大量使用本地缓存的应用会造成较大的内存浪费(把本地缓存改为集中式缓存);

二、异步请求大量累积

异步请求大量累积,当请求异常时,接口超时导致双方服务速度不对等,最终累积了大量未完成的web请求超出了虚拟机承受能力,导致崩溃。
解决:

  • 修复超时接口
  • 异步web请求改为消息队列。

三、排查问题

老实说,JVM调优是一个非常庞大问题集;着手点因为实际问题的差异也各不相同;

排查问题:

  1. jmap jstat 等指令查看堆使用情况,渐次定位问题;
  2. jvisualvm 查看Java堆各个区域回收情况,查看JVM启动参数是否合理;
  3. 生成 GC 日志查看GC类型,统计各种类型的GC次数,记录GC耗时,关注异常GC;(可以使用GC日志分析工具,也可以自己用文本文档分析);
  4. 生成堆快照并分析,查看堆内是否有某些对象数量是否异常;

可能出现的问题以及原因

  1. Full GC频繁:老年代空间较小,收集速度滞后于新生代

设置老年代:新生代比例 3:1 (通常3:1为较好的选择),G1 收集器不建议使用会破坏G1的停顿预测模型。

	-XX:NewRatio=3

拓展堆内存大小,最大最小设置相同,避免运行过程中堆内存浮动

	-Xms4192m
	-Xmx4192m
  1. Full GC 时间过长,这是本文讨论的第一个问题
    • 使用增量垃圾回收:G1 / (CMS + ParaNew)

        //G1 不区分新生代老年代
        -XX:+UseG1GC
        
        // 或者,CMS(老年代) + ParaNew(新生代)
        -XX:+UseParNewGC
        -XX:+UseConcMarkSweepGC
      

问题太多,JVM优化也只是往更优的方案靠近,没有万能的优化,只有针对具体问题的具体优化,如果后续碰到问题我会持续更新到这里。

原文地址:https://www.cnblogs.com/bokers/p/14903035.html