深入理解Java虚拟机(第一版)-第三章读书笔记

本文解析了垃圾收集器的工作原理及内存分配策略,重点介绍了GCRoots的概念及其作用范围,通过实例阐述了对象存活与回收的过程。同时,深入探讨了CMS收集器的特点与不足,以及如何优化对象大小以提高垃圾回收效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述


第三章的标题是:垃圾收集器与内存分配策略


GC Roots


首先必须吐槽一下,这个章节里,作者对GC Root的定义的描述的不太清楚的。读完之后,还是一头雾水。为了大概搞清楚这个问题,自己找了蛮多资料,下面简单的汇总描述一下。

GC Root是一组活跃的引用,不是一组对象。

这组引用包含的范围很广,为了说明问题,就以当前线程的线程栈中的引用作为例子。

public void method1() {
 Object obj = new Object(); 
}

当线程A执行了method1方法的时候,创建了一个对象,obj是其引用。那么这个obj就是GC Roots中的一种。当线程A执行完后,存在于当前线程的栈帧中的obj引用会被自动出栈,无需我们理会。而原先obj所引用的对象则存在于堆中,只能等待垃圾回收器回收。这里就有个疑问

obj已经丢失了(出栈了),那么原先obj所引用的对象如何回收呢?

这里必须澄清的是:

所谓从GC Roots这些根引用开始的根搜索算法,是寻找活跃引用对应的对象,能被找到的就是活的对象,不能被找到的对象,就可以判断为死亡,就可以被回收。

public void method2() {
 Object obj2 = new Object(); //第一行
 。。。。。。  //第二行
 。。。。。    //第三行
}

比如说,另外一个线程B执行了method2方法,并且执行了

 Object obj2 = new Object();

这个时候刚好发生Young GC,method2方法由于还未执行完(第二行和第三行代码还未执行),obj2引用属于活跃引用,从obj2开始遍历对象图,找到了obj2引用的对象。至于之前线程A创建的obj1引用所引用的对象,从obj2遍历的话,是不可达的,因此会被回收掉的。


CMS收集器


CMS收集器是一种以获取最短回收停顿时间为目标的收集器。

CMS之所以能尽量减少停顿时间,最主要的原因是在并发标记和并发清除阶段中,无需Stop The World。垃圾回收线程可以与用户线程一起工作。CMS收集器分为四个阶段:

1、初始标记:只是找到GC Roots引用能直接关联到的对象,并把这些对象的字段(比如说对象引用字段)保存到扫描栈中;
2、并发标记:对初始化标记中保存到扫描栈中的引用,递归扫描整个堆中的对象图;
3、重新标记:并发标记过程中,运行的用户线程可能导致在并发标记阶段的标记记录有变动,需要重新标记;
4、并发清除 :清除不可达对象,回收内存。

1和3需要Stop The World。

CMS收集器缺点:

1、垃圾回收线程会占用一部分CPU,如果配置的垃圾回收线程比较多,对应CPU敏感类型的应用,可能有影响;
2、会产生浮动垃圾。也即是并发标记阶段产生的垃圾,只能在下次Full GC的时候才能回收掉;

3、会导致内存碎片。


对象要尽量的小


1、不然可能提早触发Young GC;
2、可能直接将短生命周期的对象进入老年代,只能等待Full GC的时候才能回收掉。而它本来应该是在Young GC的时候就被回收掉的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值