jvm垃圾回收调优

106 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

5.垃圾回收调优

查看虚拟机参数命令,可以根据参数去查询具体的信息

"D:\JAVA\JDK8.0\bin\java" -XX:+PrintFlagsFinal -version | findstr "GC"
  • 掌握 GC 相关的 VM 参数,会基本的空间调整
  • 掌握相关工具
  • 明白一点:调优跟应用、环境有关,没有放之四海而皆准的法则

(1)调优领域

  • 内存
  • 锁竞争
  • CPU占用
  • IO
  • GC

(2)确定目标

低延迟/高吞吐量? 选择合适的GC

  • CMS G1 ZGC
  • ParallelGC
  • Zing

(3)最快的GC

最快的GC是不发生GC 首先排除减少因为自身编写的代码而引发的内存问题

  • 数据是不是太多?
    • resultSet = statement.executeQuery("select * from 大表 limit n")
  • 数据表示是否太臃肿
    • 对象图
    • 对象大小
  • 是否存在内存泄漏
    • static Map map =
    • 第三方缓存实现

(4)新生代调优

新生代的特点

  • 所有的new操作分配内存都是非常廉价的 TLAB
  • 死亡对象回收零代价
  • 大部分对象用过即死(朝生夕死)
  • MInor GC 所用时间远小于Full GC

新生代内存越大越好么?

  • 不是

    • 新生代内存太小:频繁触发Minor GC,会STW,会使得吞吐量下降
    • 新生代内存太大:老年代内存占比有所降低,会更频繁地触发Full GC。而且触发Minor GC时, 清理新生代所花费的时间会更长
  • 新生代内存设置为内容纳[并发量*(请求-响应)]的数据为宜

  • 幸存区大到能保留【当前活跃对象+需要晋升对象】

  • 晋升阈值配置得当,让长时间存活对象尽快晋升

    -XX:MaxTenuringThreshold=threshold
    -XX:+PrintTenuringDistribution
    
    Desired survivor size 48286924 bytes, new threshold 10 (max 10)
    - age 1: 28992024 bytes, 28992024 total
    - age 2: 1366864 bytes, 30358888 total
    - age 3: 1425912 bytes, 31784800 total
    ...
    

(5)老年代调优

以 CMS 为例

  • CMS 的老年代内存越大越好
  • 先尝试不做调优,如果没有 Full GC 那么已经...,否则先尝试调优新生代
  • 观察发生 Full GC 时老年代内存占用,将老年代内存预设调大 1/4 ~ 1/3
-XX:CMSInitiatingOccupancyFraction=percent

(6)案例

  • 案例1 Full GC 和 Minor GC频繁
  • 案例2 请求高峰期发生 Full GC,单次暂停时间特别长 (CMS)
  • 案例3 老年代充裕情况下,发生 Full GC (CMS jdk1.7)