作业4:垃圾回收机制

一、判断回收哪些对象
1、引用计数算法
(1)概述:对象头添加一个引用计数,其他对象引用它时,计数器加1;引用失效则减1.当计数器为0,代表对象可被回收.
(2)优点:实现简单,效率高
(3)缺点:难以解决循环引用
2、可达性分析算法
(1)概述:通过一系列称为“GC Roots”的对象作为起始点,从这些节点往下搜索,所有走过的路径称为引用链,当一个对象到GC Roots没有任何引用相连,则此对象可被回收。
(2)GC Roots对象:
  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI( Java Native Interface)引用的对象
3、java中的引用类型
(1)强引用:垃圾收集器不会回收被强引用的对象
(2)软引用:在内存不足时,垃圾收集器将回收被软引用的对象
(3)弱引用:被弱引用关联的对象在下一次垃圾收集时被回收
(4)虚引用:对象被垃圾收集器回收时将收到一个系统通知。
4、finalize方法
(1)如果对象在可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是次对象是否有必要执行finalize方法。(finalize方法执行过和对象未重写方法将视为没有必要执行)
(2)对象被判定为有必要执行时,对象被放置F-Queue的队列中,并稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去执行它。
(3)执行但不保证执行完,由于finalize方法执行缓慢或发生死循环,将影响整个内存回收系统。
5、回收方法区
(1)回收内容:废弃常量和无用的类
(2)判断无用的类:
  • 该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例
  • 加载该类的ClassLoader已经被回收
  • 该类对应的java.lang.Class对象没有在任何地方被引用
 
二、垃圾回收算法
1、标记—清除算法
(1)过程:先标记 再清除
(2)缺点:
  • 时间上效率低
  • 空间上产生大量不连续的内存碎片,分配大对象时,无法找到足够连续的内存。
2、复制算法
(1)优势:实现简单,时间高效
(2)缺点:空间利用率低
3、标记—整理算法
(1)过程:先标记,整理至一端,清除边界外内存
(2)优势:解决标记清除算法产生大量内存碎片的问题
(3)缺点:运行效率低
4、分代收集算法(综合算法)
(1)新生代:复制算法(有老年代作为内存担保)
(2)老年代:标记清除算法或标记整理算法
 
三、发起垃圾回收的时机
1、枚举根节点(Stop the world)
(1)GC Roots节点位于全局性引用(常量和类静态属性)与执行上下文(栈帧的本地变量表)中,数量庞大,逐个进行可达性分析需要消耗大量时间。
(2)GC停顿:可达性分析期间,执行系统中对象引用关系必须保持一个状态。
(3)准确式GC:执行系统停顿时,不需要检查所有执行上下文和全局引用位置,JVM能直接得知哪些地方地方存放对象引用。
        在Hotspot中,使用一组Oop(Ordinary Object Pointer,普通对象指针)Map的数据结构来实现。
2、安全点
(1)Hotspot在特定的位置(安全点)记录了Oop信息,在安全点垃圾收集器能够迅速枚举GC Roots。
(2)安全点的选定:以具有程序长时间执行的特征来选定
  • 方法调用
  • 循环跳转
  • 异常跳转等
(3)GC发生时,如何让所有线程运行至安全点才停止?
  • 抢先式中断(过期的方案):GC发生时,直接中断所有线程,如果某个线程中断位置不在安全点,则恢复线程并使其运行至安全点。
  • 主动式中断:当需要中断时,设置一个标志,各个线程执行时主动轮询整个标志,发现中断标志为真则自己中断挂起。(轮询标志的地方与安全点重合或创建对象需要分配内存的地方)
3、安全区域
(1)线程处于Sleep状态或者Blocked状态或者没有分配到时间片时无法响应JVM的中断请求,即无法在安全点进行停顿。
(2)安全区域:一段代码片段中,引用关系不会发生变化,在此区域任何地方开始GC都是安全的。
(3)线程执行到安全区域中的代码时,标识自己进入了安全区域即可;线程离开安全区域时,检查GC过程是否完成,未完成则等待。
 
四、JVM中的垃圾回收器
1、Serial收集器
  • 优势:简单高效
  • 劣势:STW时间太长
2、ParNew收集器
  • 优势:多核处理器下,效率高
  • 劣势:在单核处理器下,上下文切换开销导致性能低于Serial收集器
注意:
  • 并行(Parallel):多条垃圾收集线程并行工作,但用户线程处理等待状态
  • 并发(Concurrent):用户线程与垃圾收集线程同时执行,用户线程在一个CPU上执行,而垃圾收集线程在另一个CPU上运行。
3、Parallel Scanvenge收集器(新生代收集器且采用复制算法)
(1)特点:可调控的吞吐量(用户代运行时间/(运行用户运行代码+垃圾收集时间)),吞吐量与GC停顿成反比关系。
(2)优缺点:吞吐量提升,但GC停顿变长。
(3)开启自适应调节策略:-XX:+UseAdaptiveSizePolicy
4、Serial Old收集器(老年代收集器)
  • 与Parallel Scanvenge收集器搭配使用
  • 作为CMS收集器的后备预案
5、Parallel Old收集器
与Parallel Scanvenge收集器组合是注重吞吐量和CPU资源敏感的组合。
6、CMS收集器(标记—清除算法)
(1)追求最短停顿时间
(2)整体过程:
  • 初始记录(需要STW):标记GC Roots能直接关联到的对象,速度很快
  • 并发标记:GC Roots Tracing
  • 重新标记(需要STW):修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录
  • 并发清除:进行内存清除
(3)并发执行:并发标记和并发清除可以与用户线程一起工作。
(4)优点:GC停顿短,并行执行
(5)缺点:
  • 对CPU资源敏感
  • 无法处理浮动垃圾,收集期间的产生的垃圾需要下次回收才能处理
  • 标记清除算法产生大量内存碎片
(5)开启整理内存碎片:-XX:CMSFullGCsBeforeCompaction(默认值为0,表示每次进入FullGC都进行整理)
7、G1收集器
(1)优点:
  • 并行与并发:G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU来缩短STW的时间。
  • 分代收集
  • 空间整合:基于标记—整理算法
  • 可预测的停顿:限定垃圾回收不能超过N毫秒;
(2)可预测停顿的实现:G1能有计划地避免在整个堆中进行全区域地垃圾回收。G1跟踪各个Region里面地垃圾堆积地价值大小,在后台维护一个优先队列,每次根据允许的收集时间,优先回收价值最大的Region(Garbage First)。
(3)Remembered Set:
  • 出现原因:在G1收集器中,Region之间的对象引用以及其他收集器中的新生代与老年代之间的对象引用,虚拟机都是使用Remembered Set来避免全堆扫描。
  • 每个Region都有一个Remembered Set来与之对应,JVM发现程序在对Reference类型的数据进行写操作时,会产生一个写屏障暂时中断写操作,检查Reference引用的对象是否处于不同的Region之中,如果是,则通过CardTable把相关引用信息记录到被引用的对象所属的Region的Remembered Set中。
(4)G1收集器运作步骤:
  • 初始标记:标记一下GC Roots能直接关联到的对象,并修改TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确的可用的Region中创建对象,需要停止线程,但耗时短
  • 并发标记:GC Root开始对堆中对象进行可达性分析,找出存活对象,耗时长,但可与用于程序并发执行
  • 最终标记:修正在并发标记期间因用户程序继续运行而导致标记产生变动的那一部分标记记录,JVM将这段时间对象变化记录在线程的Remembered Set Logs中,并将记录中的数据合并至Remembered Set中,需要STW,但时间很短。
  • 筛选标记:
    • 对各个Region的回收价值和成本进行排序
    • 根据用户期望的GC停顿时间进行回收
    • 可与用户程序一起并发执行
 
五、内存分配和回收策略
1、对象优先在Eden分配:当Eden区没有足够的空间进行分配时,JVM将发起一次Minor GC
  • Minor GC:新生代垃圾收集动作
  • Full GC:老年代的GC,出现Full GC,一般伴随一次MinorGC(Parallel Scanvenge收集器的收集策略里能直接进行Full GC,即跳过Minor GC)。Full GC的速度比Minor GC慢10倍以上。
2、大对象直接进入老年代:
  • 如果对象大于新生代的剩余内存空间将直接进入老年代
  • 如果对象大于 -XX:PretenureSizeThreshold(单位是字节)  -XX:+UseSerialGC 设置的值将直接进入老年代(java8 默认采用Parallel Scanvenge垃圾收集器)
3、长期存活的对象将进入老年代:默认情况下,-XX:MaxTenuringThreshold=15,即对象在Survivor区经过15次Minor GC后将进入老年代。
4、动态对象年龄判断:如果在Surivivor空间中相同年龄所有对象的大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无需等到MaxTenuringThreshold中要求的年龄。
5、空间分配担保:

 
原文地址:https://www.cnblogs.com/linzhanfly/p/9223185.html