深入理解Java虚拟机-垃圾回收

1. 如何判断对象为垃圾对象

1.1 引用计数法

思路:在对象中添加一个引用计数器,当有地方引用这个对象时,引用计数器的值就加1,当引用失效时,引用计数器就减1。
栈中变量引用对象,引用计数器加1
栈中变量引用失效,引用计数器减1
相互引用导致双方的引用计数器均为1,不能被垃圾回收

package gc;

public class GCtest {

    private Object instance;

    public static void main(String[] args) {

        GCtest g1 = new GCtest();
        GCtest g2 = new GCtest();

        g1.instance = g2;
        g2.instance = g1;

        g1 = null;
        g2 = null;

        System.gc();
    }
}

加入虚拟机参数-verbose:gc -XX:+PrintGCDetails打印垃圾回收信息

[0.155s][info   ][gc,heap        ] GC(0) Eden regions: 3->0(2)
[0.155s][info   ][gc,heap        ] GC(0) Survivor regions: 0->0(0)
[0.155s][info   ][gc,heap        ] GC(0) Old regions: 0->2
[0.155s][info   ][gc,heap        ] GC(0) Humongous regions: 0->0
[0.155s][info   ][gc,metaspace   ] GC(0) Metaspace: 608K->608K(1056768K)
[0.155s][info   ][gc             ] GC(0) Pause Full (System.gc()) 2M->0M(8M) 5.209ms

证明垃圾被回收了,说明虚拟机采用的不是引用计数法。下面介绍可达性分析法。

1.2 可达性分析法

思路:通过一系列的的成为“GC Roots”的对象作为起始点,从这些结点开始向下搜索,搜索过的路径成为引用链,当一个对象到GC Roots没有任何引用链项链,则证明此对象是不可达的。
可达性分析法
Object5,6,7是不可达的,故它们为可回收对象
可作为GC Roots的对象:
1.虚拟机栈(栈帧中的局部变量表)中引用的对象
2.本地方法栈JNI引用的对象
3.方法区中的静态属性引用的对象
4.方法区中常量引用的对象

主流垃圾收集器所使用的方法均是可达性分析法

1.3 四种引用

强引用:只要强引用存在,垃圾收集器永远不会回收掉被引用的对象
软引用:软引用关联的对象,需要在内存不够时被垃圾回收
弱引用:弱引用引用的对象,只能生存到下一次垃圾回收之前。
虚引用:虚引用是一种最弱的引用关系,一个对象是否有虚引用的存在,不会对其生存时间构成影响,也无法通过虚引用来获取一个引用实例,设置虚引用的目的是能在这个对象被垃圾回收时收到一个系统通知。

2. 如何回收

2.1 回收策略

2.1.1 标记-清除算法

算法分为标记和清除两个阶段,收i按表基础所有需要回收的对象,在标记完成后统一回收所有被标记的碎片。
在这里插入图片描述
主要问题:
1.效率问题:标记和清楚两个过程的效率不高,
2.会产生内存碎片:标记清除后会产生大量不连续的内存虽贫,导致在以后分配大对象时提前触发垃圾收集。

2.1.2 标记-复制算法

HotSpot将新生代内存分为一个较大的Eden区域(80%)和两个较小的Survivor区域(10%+10%)。每次使用Eden和一个Survivor,当回收时,将Eden和Survivor中还存活的对象一次性的复制另一个Survivor区域,最后清理掉Eden和刚才用过的Survivor区域。
当Survivor空间不够用时,需要依赖老年代进行内存担保。
标记复制算法

2.1.3 标记-整理算法

标记-整理算法不直接对可回收对象进行清理,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。
标记整理算法

2.1.4 分代收集算法

根据对象存活周期将堆内存分为新生代和老年代,在新生代使用标记-复制算法,在老年代使用标记-清除或标记-整理算法进行回收。

2.2 垃圾收集器

HotSpot中的垃圾收集器
并发:指多条垃圾收集线程并行工作,此时用户线程处于等待状态
并行: 指用户线程和垃圾收集线程同时执行,用户程序在继续运行,而垃圾收集程序运行于另一个CPU上

2.2.1 Serial

Serial是一个单线程的收集器,在进行垃圾收集时需要暂停其他工作的线程,是虚拟机运行在Client模式下的新生代的默认新生代收集器。Serial简单高效,在单个 CPU环境下,他由于没有线程间交互和开销,可以获得最高的单线程收集效率。
在这里插入图片描述

2.2.2 Parnew

ParNew是Serial的多线程版本,是运行在Server模式下的新生代收集器,可以与CMS垃圾收集器配合使用
在这里插入图片描述

2.2.3 Parallel Scavenge

Parallel Scavenge收集器是一个新生代收集器,它的目标是达到一个可控制的吞吐量。Parrallel Scavenge收集器提供了两个参数来精确控制吞吐量,最大垃圾收集停顿时间的-XX:MaxGCPauseMillis,以及设置吞吐量大小的-XX:GCTimeRatio。GC停顿时间缩短是以牺牲吞吐量和新生代空间换取的,所以并不是把MaxGCPauseMillis设置的越小越好。
在这里插入图片描述

2.2.4 Serial Old

Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用的是标记-整理算法。主要用于Client模式下的虚拟机使用,如果用在Server模式下可以与Parallel Scavenge收集器搭配使用,也可以作为CMS再发生Concurrent Mode Failure时后使用。
在这里插入图片描述

2.2.5 Parallel Old

Parallel Old收集器是Parallel Scavenge的老年代版本。在注重吞吐量优先和CPU资源敏感的场合,可以考虑使用Parallel Old收集器。

2.2.6 CMS

CMS收集器是一种以获取最短回收停顿时间为目标的收集器。采用的是标记-清除算法,整个过程分为下列四个步骤:
1.初始标记:仅仅标记GC Roots能关联的对象,需要停顿。
2.并发标记:进行GC RootsTracing的过程,不需要停顿。
3.重新标记:是为了修正并发标记期间因用户线程运作而导致的标记产生变动的那一部分对象的标记记录,需要停顿。
4.并发清除:清除用户线程产生的垃圾,不需要停顿。

CMS收集器的缺点:
1.对CPU资源敏感,默认回收线程为(CPU数量+3)/4。
2.无法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败导致另一次Full GC的产生,由于在并发清除的过程中,仍有用户线程在工作,所以要在老年代中预留一部分空间提供并发清除时程序使用
3.采用的是标记清除-算法,在垃圾收集过后可能吹按大量的内存碎片,会给大对象带来很大的麻烦,没有连续的内存空间来分配大对象,不得不提前触发Full GC。
在这里插入图片描述

2.2.7 G1

G1收集器是同时运行在新生代和老年代的垃圾收集器,它有如下特点:
1.并发与并行:使用多个CPU来缩短停顿时间
2.分代收集:采取不同的方式来处理新创建的对象和已经存活一段时间,经过多次GC的旧对象。
3.空间整合:从整体来看是基于标记-整理算法,从局部来看是基于标记-复制算法。
4.可预测的停顿:能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾停顿的时间不能超过N毫秒。

在使用G1收集器时,Java堆被划分成多个大小相等的独立区域(Region),新生代和老年代不在物理隔离,他们是一部分Region的集合。G1跟踪各个Region的垃圾堆积价值的大小,在后台维护一个优先列表,每次根据允许回收的时间,优先回收价值最大的Region。虚拟机使用Remerbered Set来避免全堆扫描。

整个过程分为下列四个步骤:
1.初始标记:仅仅标记GC Roots能关联的对象,并且修改TAMS的值,让下一阶段用户程序并发运行时,能在正确可用的REgion中创建新对象,需要停顿。
2.并发标记:进行GC RootsTracing的过程,不需要停顿。
3.重新标记:是为了修正并发标记期间因用户线程运作而导致的标记产生变动的那一部分对象的标记记录,需要停顿。
4.筛选回收:首先对各个Region的回收价值和成本进行排序,根据用户期望的GC停顿时间来制定回收计划。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值