JVM学习打卡03

垃圾回收

一、 如何判断对象可以回收

        1.1 引用计数法

        1.2 可达性分析算法

        1.3 4种引用

(1) 强引用  
        只有所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收
(2) 软引用(SoftReference) 
        仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次触发垃圾回收,回收软引用
        对象可以配合引用队列来释放软引用自身
(3) 弱引用(WeakReference)
        仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象可以配合引用队列来释放弱引用自身
(4) 虚引用(PhantomReference)
        必须配合引用队列使用,主要配合 ByteBuffer 使用,被引用对象回收时,会将虚引用入队,
        由 Reference Handler 线程调用虚引用相关方法释放直接内存
(5) 终结器引用(FinalReference)
        无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象
        暂时没有被回收),再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 fifinalize
        方法,第二次 GC 时才能回收被引用对象

二、垃圾回收算法

        2.1 标记清除

                速度快,会造成内存碎片

        2.2 标记整理

                速度慢,没有内存碎片

         2.3 复制算法

                不会有内碎片,需要占用双倍内存空间

 三、分代垃圾回收

        (1) 对象首先分配在伊甸园区域
        (2) 伊甸园空间不足时,触发 minor gc,伊甸园和 from 存活的对象使用 copy 复制到 to 中,存活的对象年龄加 1并且交换 from to
        (3) minor gc 会引发 stop the world,暂停其它用户的线程,等垃圾回收结束,用户线程才恢复运行 当对象寿命超过阈值时,会晋升至老年代,最大寿命是154bit
        (4)当老年代空间不足,会先尝试触发 minor gc,如果之后空间仍不足,那么触发 full gc,STW的时间更长

        3.1 相关VM参数

四、垃圾回收器 

        4.1 串行

                serial(工作在新生代,采用复制算法)

                serialOld(工作在老年代,采用标记+整理算法)

        4.2 吞吐量优先

                ParallelGC(1.8JDK默认开启,并行的垃圾垃圾回收器)

                UseParallelGC(工作在新生代,采用复制算法)

                UseParallelOldGC(工作在老年代,采用标记+整理算法)

        4.3 响应时间优先(concurrent+mark+sweep)        并发

                有些阶段需要(stop  the world),在垃圾回收阶段不需要(stop  the world),可以                  和用户线程并发执行

                UseConcMarkSweepGC(工作在老年代的垃圾回收器,标记+清除算法),由于是并发                    清除算法,碎片太多造成并发失败,垃圾回收器就不能正常工作,就会退化为SerialOld

                UseParNewGC(工作在新生代,复制算法)

        4.4 G1  (并发)

        (1) 垃圾回收阶段

         (2) Young Collection

                垃圾回收器将整个堆内存划分成大小相等一个个的区域,每个区域都可以作为伊甸园,                  幸存区和老年代

                 执行一段时间以后,新生代内存紧张了,就会执行垃圾回收的操作,将幸存对象复制进                 幸存区

                 再工作一段时间,当幸存区的对象也比较多了,并且幸存区的年龄超过一定时间,会触                   发新生代的垃圾回收,有一部分会晋升到老年代,年龄不够的又会拷贝到幸存区

        (3) Young Collection + CM     

                在 Young GC 时会进行 GC Root 的初始标记
                老年代占用堆空间比例达到阈值时,进行并发标记(不会 STW),由下面的 JVM 参数                  决定

                 (4) Mixed Collection

                        会对 E、S O 进行全面垃圾回收(优先收集垃圾最多的区域)
                        最终标记(Remark)会 STW
                        拷贝存活(Evacuation)会 STW
                        -XX:MaxGCPauseMillis=ms

                (5) Full GC

                        SerialGC
                                新生代内存不足发生的垃圾收集 - minor gc
                                老年代内存不足发生的垃圾收集 - full gc
                        ParallelGC
                                新生代内存不足发生的垃圾收集 - minor gc
                                老年代内存不足发生的垃圾收集 - full gc
                        CMS
                                新生代内存不足发生的垃圾收集 - minor gc
                                老年代内存不足
                        G1
                                新生代内存不足发生的垃圾收集 - minor gc
                                老年代内存不足
                (6) Young Collection 跨代引用 Young Collection 跨代引用
                
                卡表与 Remembered Set
                在引用变更时通过 post-write barrier + dirty card queue
                concurrent refinement threads 更新 Remembered Set
                (7) Remark

                         pre-write barrier + satb_mark_queue

                 

                (8) JDK 8u20 字符串去重

                        优点:节省大量内存
                        缺点:略微多占用了 cpu 时间,新生代回收时间略微增加

                (9) JDK 8u40 并发标记类卸载  

                        所有对象都经过并发标记后,就能知道哪些类不再被使用,当一个类加载器的所有                          类都不再使用,则卸载它所加载的所有类
                        -XX:+ClassUnloadingWithConcurrentMark 默认启用
                (10) JDK 8u60 回收巨型对象
                        一个对象大于 region 的一半时,称之为巨型对象
                        G1 不会对巨型对象进行拷贝
                        回收时被优先考虑
                        G1 会跟踪老年代所有 incoming 引用,这样老年代 incoming 引用为0 的巨型对象                            就可以在新生代垃圾回收时处理掉

                (11) JDK 9 并发标记起始时间的调整

                        并发标记必须在堆空间占满前完成,否则退化为 FullGC
                        JDK 9 之前需要使用 -XX:InitiatingHeapOccupancyPercent
                        JDK 9 可以动态调整
                                -XX:InitiatingHeapOccupancyPercent 用来设置初始值
                                进行数据采样并动态调整
                                总会添加一个安全的空档空间

五、垃圾回收调优

        5.1 调优领域

                内存
                锁竞争
                cpu 占用
                io
        
        5.2 确定目标
                
               【低延迟】还是【高吞吐量】,选择合适的回收器
                CMS,G1 ZGC
                ParallelGC
                Zing
        
        5.3  新生代调优
            
                新生代的特点
                        所有的 new 操作的内存分配非常廉价
                                TLAB thread-local allocation buffffer
                        死亡对象的回收代价是零
                        大部分对象用过即死
                        Minor GC 的时间远远低于 Full GC
                        新生代能容纳所有【并发量 * (请求- 响应 ) 】的数据
                        幸存区大到能保留【当前活跃对象+需要晋升对象】
                        晋升阈值配置得当,让长时间存活对象尽快晋升
                                -XX:MaxTenuringThreshold=threshold(调整最大阈值)
                                -XX:+PrintTenuringDistribution
        5.4 老年代调优
                以 CMS 为例
                        CMS 的老年代内存越大越好
                        先尝试不做调优,如果没有 Full GC 那么已经OK(老年代空间很充裕),否则先                            尝试调优新生代
                        观察发生 Full GC 时老年代内存占用,将老年代内存预设调大 1/4 ~ 1/3
                                -XX:CMSInitiatingOccupancyFraction=percent
        5.5 案例
                
                案例 1  Full GC Minor GC频繁
                        GC特别频繁,说明空间紧张。如果是新生代空间紧张,当业务高峰期来了,大量                            的对象被创建,很快就把新生代空间塞满了,造成幸存区晋升空间阈值降低,导致                          很多生存周期很短的对象也会被晋升到老年代去,进而导致老年代频繁触发Full                         GC的发生
                        解决 :先试着增大新生代内存,内存充裕了,新生代的垃圾回收就变得不那么频繁                                     了,同时增大幸存区的空间和晋升阈值,这样就这一个让生命周期较短的对                                     象尽可能的留在新生代,而不晋升到老年代,这样进一步让老年代的Full                                         GC不那么频繁
                案例2  请求高峰期发生 Full GC,单次暂停时间特别长 (CMS
                        解决首先是去查看GC日志,看看CMS的哪个阶段花费的时间较长
                        在重新标记之前,先对新生代的垃圾做一次标记清理,清理之后,在重新标记阶                              段,需要查找和标记的对象也要少的多
                案例3 老年代充裕情况下,发生 Full GC (CMS jdk1.7)

                         解决:jdk1.8是有一个元空间作为方法区的实现;jdk1.7以前的是采用永久代作为                                      方法区的实现,永久代的空间不足导致Full GC的发生;jdk1.8以后的元空                                      间的内存空间默认是使用操作系统的内存空间。增大永久代的初始值和最                                        大值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值