GC和GC Tuning

GC和GC Tuning

作者:fcl

GC的基础知识

1.什么是垃圾

C语言申请内存:malloc申请内存, free释放内存

C++: new申请内存, delete释放内存

C/C++: 手动回收内存

Java::new 申请内存 ?(JVM自动回收内存)

自动内存回收,编程上简单,系统不容易出错,手动释放内存,容易出两种类型的问题:

  1. 忘记回收:造成内存泄漏和内存溢出等问题
  2. 多次回收:垃圾回收方法可能封装在if/else等判断语句中,多次回收造成将有用的数据回收掉…

没有任何引用指向的一个对象或者多个对象循环引用被称为垃圾

2.如何定位垃圾
  1. 引用计数(ReferenceCount)
  2. 根可达算法(RootSearching)
3.常见的垃圾回收算法
  1. 标记清除(mark sweep) - 位置不连续 产生碎片 效率偏低(两遍扫描)
  2. 拷贝算法 (copying) - 没有碎片,浪费空间
  3. 标记压缩(mark compact) - 没有碎片,效率偏低(两遍扫描,指针需要调整:第一遍和标记清楚类似找出非垃圾的对象,第二遍调整指针,注意在调整指针时如果是单线程效率偏低,如果是多线程需要线程同步也会影响效率,所以说最终结论是效率偏低,但是没有产生碎片化)
  4. 分代收集算法() - 是将内存分为年轻代-老年代(然后配合上述三种垃圾回收算法使用)
4.JVM内存分代模型(用于分代垃圾回收算法)
  1. 部分垃圾回收器使用的模型

    除Epsilon ZGC Shenandoah之外的GC都是使用逻辑分代模型

    G1是逻辑分代,物理不分代

    除此之外不仅逻辑分代,而且物理分代

  2. 新生代 + 老年代 + 永久代(1.7)Perm Generation/ 元数据区(1.8) Metaspace

    1. 永久代:方法区(在java虚拟中)
    2. 元数据 - 元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用 本地内存
    3. 永久代必须指定大小限制 ,元数据可以设置,也可以不设置,无上限(受限于物理内存,动态分配)
    4. 字符串常量 1.7 - 在永久代,1.8 - 在堆
    5. MethodArea逻辑概念 - 1.8之前叫永久代、1.8之后叫元数据
    6. 元数据区不受堆内存的管理,操作系统直接参与管理元数据区。

    永久代变更为元数据区的大概原因:
    1、字符串存在永久代中,容易出现性能问题和内存溢出。
    2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
    3、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。

  3. 新生代 = Eden + 2个suvivor区

    1. YGC回收之后,大多数的对象会被回收,活着的进入s0
    2. 再次YGC,活着的对象eden + s0 <相互移动> s1
    3. 再次YGC,eden + s1 -> s0
    4. 年龄足够 -> 老年代 (15 CMS 6)分代年龄占4个Bit所以最大值为15
    5. s区装不下 -> 老年代(分配担保机制)
  4. 老年代

    1. 顽固分子
    2. 老年代满了 Full GC
  5. GC Tuning 的核心思想(Generation)

    1. 尽量减少FGC(full gc将会把老年代and年轻代全部gc一遍,耗时巨大,造成长时间的STW)
    2. MinorGC = YGC
    3. MajorGC = FGC
  6. 对象分配过程图
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-acE0cm6H-1597474966815)(对象分配过程详解.png)]

  7. 动态年龄:(不重要)
    https://www.jianshu.com/p/989d3b06a49d

  8. 分配担保:(不重要)
    YGC期间 survivor区空间不够了 空间担保直接进入老年代
    参考:https://cloud.tencent.com/developer/article/1082730

5.常见的垃圾回收器
  1. 垃圾回收器的发展路线,是随着内存越来越大的过程而演进
    从分代算法演化到不分代算法
    Serial算法 几十兆
    Parallel算法 几个G
    CMS 几十个G - 承上启下,开始并发回收 -
    .- 三色标记 -
    G1 几百个G(Region小区块)
    ZGC 几个T(Region小区块)

  2. JDK诞生 Serial追随 提高效率,诞生了PS,为了配合CMS,诞生了PN,CMS是1.4版本后期引入,CMS是里程碑式的GC,它开启了并发回收的过程,但是CMS毛病较多,因此目前任何一个JDK版本默认是CMS
    并发垃圾回收是因为无法忍受STW

  3. Serial 年轻代 串行回收

  4. PS 年轻代 并行回收

  5. ParNew 年轻代 配合CMS的并行回收

  6. SerialOld

  7. ParallelOld

  8. ConcurrentMarkSweep 老年代 并发的, 垃圾回收和应用程序同时运行,降低STW的时间(200ms)
    CMS问题比较多会产生漏标和错标,所以现在没有一个版本默认是CMS,只能手工指定
    CMS既然是MarkSweep,就一定会有碎片化的问题,碎片到达一定程度,CMS的老年代分配对象分配不下的时候,使用SerialOld 进行老年代回收(SerialOld单线程STW回收大内存的垃圾时效率低)
    算法:三色标记(黑:已经标记完成,灰:标记完自身,自身属性的引用未标记,白:未标记) +
    Incremental Update:当黑色对象插入新的指向白色对象的引用关系时,就将这个新插入的引用记录下来,等并发扫描结束之后,再将这些记录过的引用关系中的黑色对象为根,重新扫描一次。这可以简化理解为,黑色对象一旦新插入了指向白色对象的引用之后,它就变回灰色对象了。

  9. G1(200ms - 10ms)
    算法:三色标记(黑:已经标记完成,灰:标记完自身,自身属性的引用未标记,白:未标记) + SATB(起始快照算法)和CMS类似,在最后重新标记时采用STW方式,同时使用STW方式clear
    G1详解:https://blog.youkuaiyun.com/coderlius/article/details/79272773

  10. ZGC (10ms - 1ms) PK C++ (整合了CMS和G1的优势)
    算法:(彩色指针+读屏障)ColoredPointers + LoadBarrier

  11. Shenandoah
    算法:(彩色指针+写屏障)ColoredPointers + WriteBarrier
    彩色指针详解:https://blog.youkuaiyun.com/xiaolyuh123/article/details/103937164
    读写屏障详解:https://blog.youkuaiyun.com/kuaipao19950507/article/details/106821010

  12. Eplison

  13. PS 和 PN区别的延伸阅读:
    https://docs.oracle.com/en/java/javase/13/gctuning/ergonomics.html#GUID-3D0BB91E-9BFF-4EBB-B523-14493A860E73

  14. 垃圾收集器跟内存大小的关系

    1. Serial 几十兆
    2. PS 上百兆 - 几个G
    3. CMS - 20G
    4. G1 - 上百G
    5. ZGC - 4T - 16T(JDK13)

1.8默认的垃圾回收:PS + ParallelOld

常见垃圾回收器组合参数设定:(1.8)

  • -XX:+UseSerialGC = Serial New (DefNew) + Serial Old

    • 小型程序。默认情况下不会是这种选项,HotSpot会根据计算及配置和JDK版本自动选择收集器
  • -XX:+UseParNewGC = ParNew + SerialOld

    • 这个组合已经很少用(在某些版本中已经废弃)
    • https://stackoverflow.com/questions/34962257/why-remove-support-for-parnewserialold-anddefnewcms-in-the-future
  • -XX:+UseConc(urrent)MarkSweepGC = ParNew + CMS + Serial Old

  • -XX:+UseParallelGC = Parallel Scavenge + Parallel Old (1.8默认) 【PS + SerialOld】

  • -XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old

  • -XX:+UseG1GC = G1

  • Linux中没找到默认GC的查看方法,而windows中会打印UseParallelGC

    • java +XX:+PrintCommandLineFlags -version
    • 通过GC的日志来分辨
  • Linux下1.8版本默认的垃圾回收器到底是什么?

    • 1.8.0_181 默认(看不出来)Copy MarkCompact
    • 1.8.0_222 默认 PS + PO

JVM调优第一步,了解JVM常用命令行参数

  • JVM的命令行参数参考:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

  • HotSpot参数分类

    标准: - 开头,所有的HotSpot都支持

    非标准:-X 开头,特定版本HotSpot支持特定命令

    不稳定:-XX 开头,下个版本可能取消

    java -version

    java -X

    java -XX:+PrintFlagsWithComments //只有debug版本能用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值