说起垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物。事实上,GC的历史远比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言。当List还在胚胎时期时,人们就在思考GC需要完成的3件事情:

一、哪些内存需要回收?
从JVM区域结构看,可将这些区域划分为“静态内存”和“动态内存”两类。程序计数器、虚拟机栈、本地方法3个区域是“静态”的,因为这几个区域的内存分配和回收都具备确定性,都随着线程而生,随着线程而灭。但Java堆和方法区不一样,内存分配都存在不确定性,只有在程序处于运行期间才能知道会创建哪些对象,这部分内存和回收都是动态的,垃圾收集器所关注的是这部分内存。
在堆里面存放着Java世界几乎所有的对象实例,垃圾回收器在对堆进行回收前,第一件事情就是就是要确定这些对象哪些还"存活"着,哪些已经"死去"。那么又怎么确定对象已经"死去"呢?
1.引用计数法:
分配对象时给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是没有再被使用了。客观地说,引用计数法(Reference Counting)的实现简单,判断效率也很高,但是在主流的Java虚拟机里面没有选用引用计数法来管理内存,其中最主要的原因是它很难解决对象之间相互循环引用的问题。例如:
public class ReferenceCountingGC {
public Object instance = null;
private byte[] bigsize = new byte[2*1024*1024];
public static void testGC(){
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
System.gc();
}
}
当设置objA = null;objB = null后这两个对象再无任何引用,实际上这两个对象已经不可能再被访问,但是它们因为互相引用着对方,导致它们的引用计数都不为0,于是引用计数算法无法通知GC收集器回收它们。如果这个对象特别大,则会造成严重的内存泄露。
2.可达性分析算法:
可达性分析(Reachability Analysis)的基本思想是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时(也就是GC Roots到这个对象不可达),则证明此对象是不可用的。如下图所示:
对象Object5、Object6、Object7相互虽然有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。在Java语言中,可作为GC Roots的对象包括下面几种:
二、什么时候回收?
虚拟机为了分析GC Roots这项工作必须在一个能确保一致性的快照中进行,这里的“一致性”的意思就是指在整个分析期间整个执行系统看起来就像被冻结在某个时间点上——这叫安全点。当然,程序执行时并非在所有地方都能停顿下来开始GC,只有到达安全点时才能暂停。安全点选址也有规定的,选定基本上是以程序“是否具有让程序长时间执行的特征”为标准进行选定的。这里的长时间执行的最明显特征是指令列复用,例如方法调用、循环跳转、异常跳转等。
虚拟机为了能让所有线程都“跑”到安全点上停顿下来,设计了两个方案:抢先式中断和主动式中断。其中抢先式中断是虚拟机发生GC时,首先把所有线程全部中断,如果发生有线程中断的地方不在安全点上,就恢复线程,让它“跑”到安全点上。这种方式现在比较用了。而主动式中断是虚拟机需要GC时仅仅简单的设置一个标志,各个线程执行到安全点时主动去轮询这个标志,发现中断标志为真时就自己中断挂起。
三、如何回收?
3.1 垃圾收集算法:
(1)标记-清除(Mark-Sweep)算法
这是最基础的算法,就像它名字一样,算法分为“标记”和“清除”两个阶段:首先标记处所有需要回收的对象(如哪些内存需要回收所描述的对象),对标记完成后统一回收所有被标记的对象,如下图所示:
缺点:一个是效率问题,标记和清除两个过程的效率都不高;另一个是空间问题,标记清除后悔产生大量的不连续的内存碎片,可能会导致后续无法分配大对象而导致再一次触发垃圾收集动作。
(2)复制算法
为了针对标记-清除算法的不足,复制算法将可用内存容量划分为大小相等的两块,每次只使用一块。当一块的内存用完了,就将还存活的对象复制到另一块上面去。然后把已使用过的内存空间一次清理掉,如下图所示:
缺点:使用内存比原来缩小了一半。
现在的商业虚拟机都采用这种收集算法来回收新生代,有企业分析的得出其实并不需求将内存按1:1的比例划分,因为新生代中的对象大部分都是“朝生夕死”的。所以,HotSpot虚拟机默认的Eden和Survivor的大小比例是8:1。一块Eden和两块Survivor,每次使用一块Eden和一块Survivor,也就是说只有10%是浪费的。如果另一块Survivor都无法存放上次垃圾回收的对象时,那这些对象将通过“担保机制”进入老年代了。
(3)标记-整理(Mark-Compact)算法
复制算法一般是对对象存活率较低的一种回收操作,但对于对象存活率较高的内存区域(老年代)来说,效果就不是那么理想了,标记-整理算法因此诞生了。标记-整理算法和标记-清除算法差不多,都是一开始对回收对象进行标记,但后续不是直接对对象清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存,如下图所示:
(4)分代收集算法
分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。
3.2 垃圾收集器:
(1)七种垃圾收集器:
说明:
注意:并行与并发
(2)常用五种组合:
(2.1)Serial/Serial Old:
特点:
说明:
STW(stop the world):编译代码时为每一个方法注入safepoint(方法中循环结束的点、方法执行结束的点),在暂停应用时,需要等待所有的用户线程进入safepoint,之后暂停所有线程,然后进行垃圾回收。
适用场合:
(2.2)ParNew/Serial Old:
说明:
ParNew除了采用多GC线程来实现复制算法以外,其他都与Serial一样,但是此组合中的Serial Old又是一个单GC线程,所以该组合是一个比较尴尬的组合,在单CPU情况下没有Serial/Serial Old速度快(因为ParNew多线程需要切换),在多CPU情况下又没有之后的三种组合快(因为Serial Old是单GC线程),所以使用其实不多。
-XX:ParallelGCThreads:指定ParNew GC线程的数量,默认与CPU核数相同,该参数在于CMS GC组合时,也可能会用到
(2.3)Parallel Scavenge/Parallel Old:
特点:
说明:
参数设置:
适用场合:
(2.4)ParNew/CMS:
说明:
特点:
1.年轻代ParNew收集器采用多个GC线程实现"复制"算法(包括扫描、复制)
2.年老代CMS收集器采用多线程实现"标记-清除"算法
3.初始标记与重新标记都会暂停所有用户线程(即STW),但是时间较短;并发标记与并发清理时间较长,但是不需要STW
关于并发标记期间怎样记录发生变动的引用关系对象,在重新标记期间怎样扫描这些对象
缺点:
参数设置:
适用场合:
用于处理很多的交互任务的情况
方法区的回收一般使用CMS,配置两个参数:-XX:+CMSPermGenSweepingEnabled与-XX:+CMSClassUnloadingEnabled
适用于一些需要长期运行且对相应时间有一定要求的后台程序
(2.5)G1
说明:
原理:
运作流程:
优点:
适用范围:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
# JVM
# 垃圾收集器
# JVM垃圾回收机制和垃圾回收器详细解说
# JVM常见垃圾收集器学习指南
# 如何查看JVM使用的默认的垃圾收集器
# JVM常用垃圾收集器及GC算法解读
# 收集器
# 多个
# 都是
# 所示
# 就好
# 点上
# 遍历
# 划分为
# 如下图
# 时间内
# 越好
# 是一个
# 情况下
# 主要用于
# 多线程
# 就像
# 不需要
# 什么时候
# 长时间
# 较高
相关文章:
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
制作网站公司那家好,网络公司是做什么的?
小程序网站制作需要准备什么资料,如何制作小程序?
如何通过多用户协作模板快速搭建高效企业网站?
建站之星客服服务时间及联系方式如何?
早安海报制作网站推荐大全,企业早安海报怎么每天更换?
宝华建站服务条款解析:五站合一功能与SEO优化设置指南
网站图片在线制作软件,怎么在图片上做链接?
青岛网站设计制作公司,查询青岛招聘信息的网站有哪些?
制作网站的网址是什么,请问后缀为.com和.com.cn还有.cn的这三种网站是分别是什么类型的网站?
想学网站制作怎么学,建立一个网站要花费多少?
上海网站制作网站建设公司,建筑电工证网上查询系统入口?
建站之星后台管理:高效配置与模板优化提升用户体验
攀枝花网站建设,攀枝花营业执照网上怎么年审?
建站之星会员如何解锁更多建站功能?
,想在网上投简历,哪几个网站比较好?
如何在万网ECS上快速搭建专属网站?
湖州网站制作公司有哪些,浙江中蓝新能源公司官网?
娃派WAP自助建站:免费模板+移动优化,快速打造专业网站
公司门户网站制作流程,华为官网怎么做?
官网自助建站系统:SEO优化+多语言支持,快速搭建专业网站
相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?
如何用美橙互联一键搭建多站合一网站?
c++23 std::expected怎么用 c++优雅处理函数错误返回【详解】
C++如何将C风格字符串(char*)转换为std::string?(代码示例)
如何通过虚拟主机空间快速建站?
高端建站如何打造兼具美学与转化的品牌官网?
如何零基础在云服务器搭建WordPress站点?
建站之家VIP精选网站模板与SEO优化教程整合指南
建站之星24小时客服电话如何获取?
如何选择高效可靠的多用户建站源码资源?
阿里云网站搭建费用解析:服务器价格与建站成本优化指南
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
建站中国官网:模板定制+SEO优化+建站流程一站式指南
香港服务器如何优化才能显著提升网站加载速度?
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
建站之星2.7模板快速切换与批量管理功能操作指南
如何选择PHP开源工具快速搭建网站?
装修招标网站设计制作流程,装修招标流程?
建站ABC备案流程中有哪些关键注意事项?
教学网站制作软件,学习*后期制作的网站有哪些?
网站制作公司排行榜,抖音怎样做个人官方网站
建站之星如何助力企业快速打造五合一网站?
小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?
股票网站制作软件,网上股票怎么开户?
三星网站视频制作教程下载,三星w23网页如何全屏?
c++怎么编写动态链接库dll_c++ __declspec(dllexport)导出与调用【方法】
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
如何生成腾讯云建站专用兑换码?
北京营销型网站制作公司,可以用python做一个营销推广网站吗?
*请认真填写需求信息,我们会在24小时内与您取得联系。