Java虚拟机学习笔记第二章第二部分

Java虚拟机学习笔记第二章第二部分
引用
1.强引用
强引用即直接new一个对象,强引用还在,GC永远不会回收。
2.软引用(softReference)

如果有内存溢出的可能,先回收软引用。

SoftReference<SoftObject> reference = new SoftReference<>(new SoftObject());

软引用有两个构造方法与一个get方法,以下弱引用同理。

3.弱引用(weakReference)

在下一次垃圾回收的时候自动回收,无论是否有内存溢出可能。

4.虚引用(PhantomReference)

不影响对象的生存周期,无法得到对象实例,使用方法,唯一目的是对象被回收之后发送一个系统通知。

Object  object = new Object();
ReferenceQueue queue = new ReferenceQueue();
// 虚引用,必须与一个引用队列关联
PhantomReference A = new PhantomReference(object, queue);

虚引用需要关联一个队列,在对象被消除的时候,将虚引用添加到队列中。

应用于对象被清楚后得到通知进行更深一层次的回收。

对象的自我拯救

​ 对象被清理时会标记两次。首先对空对象第一次标记。

执行finalize()方法,并添加到F-queue队列,对象在被赋值为null之后,如果重写了finalize方法,与对象创建了关联,那么对象就不会被清除,即完成了自我拯救。(finalize方法并不会一直执行,也就是说会被中断,保证不会停滞)

如果没有重写finalize方法或者已经被调用过一次,那么会进行第二次标记并回收。

方法区的回收

​ 方法区的回收分为两类,常量的回收与废弃类的回收。

​ 对于常量: 类似对象回收,常量池中的常量未被引用,之后就会被回收。

​ 对于类:需要满足三个条件。

1.不存在实例。

2.Classloader(类加载)被回收

3.对象没被引用,类方法不能被调用。

满足三个条件之后可以被回收。-Xnoclassgc控制类的回收。常用于经常自定义Classloader的场景。

垃圾回收算法
标记清除算法

​ 第一轮标记,第二轮清除。

​ 存在两个问题,效率不高,空间清理之后碎片化。

复制算法

​ 复制算法会将内存进行分块,仅使用一块,当满了之后会将其中的仍然存活对象复制到另一块中,并将原来的那块清理,留作备用。操作上只需要移动堆顶指针,空间上并没有碎片化的问题。由于新生代的朝生夕死特性,可将内存分为8:1:1三部分,其中的8(Eden)和一块1(Survior)用来存储,另一块1(Survior)用来备用,做到了只浪费1/10的空间的复制算法,如果存活的对象大于1/10,会用老年代的空间进行担保,具体 担保之后学习。

标记整理算法

​ 显然老年代的对象特点不允许它支持复制算法,因此诞生了标记整理算法,它将所有存活的对象向一端移动,清除边界以外的内存。

​ 分代收集,一般在新生代采用复制算法,在老年代采用标记清除或者标记整理算法。

垃圾收集器
Serial收集器(新)

​ 最原始的收集器,常应用于Client端,Stop the world,停止线程进行垃圾收集,在单CPU的情况下省去了切换线程带来的麻烦。

ParNew收集器(新)

​ Serial的多线程版本。运行在Server端,可与CMS(老)配合,CMS无法与Parallel Scavenge(新生代收集器)配合。

Parallel Scavenge收集器(新)

​ 注重吞吐量,多线程,有利于完成任务,这个收集器有一个GC自适应调节,能够自动调节而参数。多线程,应该是Server端,不确定。

Serial Old (老)

​ 老年代收集器,Serial的老年代收集版本,用在Client端,用在Server端时还能Parallel Scavenge搭配,和作为CMS的备用。在并发失败Concurrent’‘ Mode Future 时使用。

Parallel Old(老)

​ 用于与Parallel scavenge 配合,实现真正的吞吐量控制。

CMS(老)

​ CMS分为初始标记,并发标记,重新标记,并发清理四个过程,初始标记标记了GC roots,并发标记在程序运行的时候进行Tracing,之后重新标记程序运行时新产生的垃圾,时间比初始标记长,比并发标记短。之后进行并发清除。

​ 减少了响应时间,增大了用户体验。

​ 缺点很明显:1.并发处理,消耗了用户CPU资源,在CPU少的情况下格为显著,采取清理与程序运行交替运行的方式能够解决,但是垃圾收集时间会变长,效果一般,已废弃。2.并发标记的垃圾能够被重新标记处理,但是并发清理的过程中产生的垃圾无法被处理,这部分垃圾被称为浮动垃圾,因此,在老年代垃圾收集的时候需要预留一部分空间,因此不能等到老年代已经被充满才进行清理,在JDK1.6中,这个阈值为92%,如果预留的空间不够的话,就会发生Concurrent Mode Future,然后启动Serial Old备案。3.因为CMS是基于标记清除的,因此会产生空间碎片的问题,这会导致提前Full GC,在这时,CMS在Full GC之前添加了合并整理过程,这并不是并发的,因此会导致停顿时间变长。另外还提供了参数,来设置几次FullGC之后进行一次带合并整理的FullGC,默认是0,每次都进行。

G1(全)

​ G1是一个比较前沿的技术,它的目的是替换掉CMS。

​ 优点:1.并发,同CMS。2.分代,保留了分代的概念,但并不是物理隔离3.标记整理,除去了空间碎片化的问题。4.可预测停顿,通过一个后代维护的优先列表,在有限的时间里能够优先回收价值最大的Region。

​ 在Region之间相互调用的时候,采用Remembered Set避免全堆扫描,每一个Region都有一个对应的Set,当存在Reference数据的写操作时,中断,并检查是否引用的对象在不同Region中,如果是的话,比如老年代对象引用了新生代对象的时候,将信息记录在被引用对象(新生代)的Set中,在GC根节点枚举的过程中加入RememberedSet防止对象遗漏。

​ 不算RememberedSet的维护,G1大概分为四步,初始标记,并发标记,最终标记,筛选回收。

初始标记,并发标记,与CMS几乎一样,在初始标记阶段,需要更新一下TAMS,TAMS是一种指针TAMS原理图
原理参考 [深入解析java虚拟机:Mixed GC(混合回收)G1独有的回收策略 (cdmana.com)]
(https://cdmana.com/2022/01/202201210048506792.html) 图片并不来自本人,复制上传的时候自动加的Logo,如有侵权,必删。

最终标记对于并发标记产生的对象数据添加到Remembered Set Logs中与Remembered Set进行合并。

​ 对于CMS中的问题,1.并发占资源问题,书中并没有给出答案。2.浮动垃圾,在G1中采用了暂停线程来进行筛选回收,算是一种一般的解决方法,另外G1也可以与用户并行回收垃圾,不过个人认为会产生浮动垃圾,不确定。3.空间碎片,已解决。

​ 对于G1,由于是未成熟产品,无太多数据检验,书中的数据我看不太懂,总结如下:

。2.浮动垃圾,在G1中采用了暂停线程来进行筛选回收,算是一种一般的解决方法,另外G1也可以与用户并行回收垃圾,不过个人认为会产生浮动垃圾,不确定。3.空间碎片,已解决。

​ 对于G1,由于是未成熟产品,无太多数据检验,书中的数据我看不太懂,总结如下:

​ 追求停顿,用户体验的话,可以尝试G1,追求吞吐量,G1是不太可以的,Parnew+CMS的组合依旧可以满足目前的所有要求,G1的发展前景很光明。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值