JVM垃圾回收机制是什么?
JVM垃圾回收机制是什么?
一. 什么是垃圾回收(GC)
JVM的内存结构包括五大区域:程序计数器、虚拟机栈、本地方法栈、堆区、方法区。
其中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生、随线程而灭,因此这几个区域的内存分配和回收都具备确定性,就不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了。而Java堆区和方法区则不一样、不一样,这部分内存的分配和回收是动态的,我们需要对不在使用的对象进行处理回收过期的对象(垃圾)从而释放JVM内存空间
二. 什么时候回收
2.1 概述
在垃圾回收之前,我们必须确定的一件事就是对象是否存活?这就牵扯到了判断对象是否存活的算法
了。
2.2 引用计数算法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器+1,当引用失效,计数器-1.任何时刻
计数器为0的对象就是不可能再被使用的
优点:实现简单,判定效率高效,被actionscript3和python中广泛应用。
缺点:无法解决对象之间的相互引用问题。java没有采纳
2.3 可达性分析算法
通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GCRoots没有任何引用链相连的时候,则证明此对象是不可用的。
比如如下,右侧的对象是到GCRoot时不可达的,可以判定为可回收对象
在java中,可以作为GCRoot的对象包括以下几种
* 虚拟机栈中引用的对象。
* 方法区中静态属性引用的对象。
* 方法区中常量引用的对象。
* 本地方法中JNI引用的对象。
基于以上,我们可以知道,当当前对象到GCRoot中不可达时候,即会满足被垃圾回收的可能。
那么是不是这些对象就非死不可,也不一定,此时只能宣判它们存在于一种“缓刑”的阶段,要真正的宣告一个对象死亡。至少要经历两次标记
第一次:对象可达性分析之后,发现没有与GCRoots相连接,此时会被第一次标记并筛选。
第二次:对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,此时会被认
定为没必要执行。
三. 如何回收
3.1 概述
上述的两点讲解之后,我们大概明白了,哪些对象会被回收,以及回收的依据是什么,但回收的这个工作实现起来并不简单,首先它需要扫描所有的对象,鉴别谁能够被回收,其次在扫描期间需要 ” stop the world“ 对象能被冻结,不然你刚扫描,他的引用信息有变化,你就等于白做了
3.2 分代回收
我们从一个object1来说明其在分代垃圾回收算法中的回收轨迹
step01 object1新建,出生于新生代的Eden区域
step02 minor GC,object1 还存活,移动到Fromsuvivor空间,此时还在新生代
step03
minor GC,object1 仍然存活,此时会通过复制算法,将object1移动到ToSuv区域,此时object1
的年龄age+1
step04 minor GC,object1 仍然存活,此时survivor中和object1同龄的对象并没有达到survivor的一半, 所以此时通过复制算法,将fromSuv和Tosuv 区域进行互换,存活的对象被移动到了Tosuv
step05 minor GC,object1 仍然存活,此时survivor中和object1同龄的对象已经达到survivor的一半以上 (toSuv的区域已经满了),object1被移动到了老年代区域
step06
object1存活一段时间后,发现此时object1不可达GcRoots,而且此时老年代空间比率已经超过了阈
值,触发了majorGC(也可以认为是fullGC,但具体需要垃圾收集器来联系),此时object1被回收了。
fullGC会触发 stop the world
在以上的新生代中,我们有提到对象的age,对象存活于survivor状态下,不会立即晋升为老生代对
象,以避免给老生代造成过大的影响,它们必须要满足以下条件才可以晋升
1、minor gc 之后,存活于survivor 区域的对象的age会+1,当超过(默认)15的时候,转移到老年代
2.、动态对象,如果survivor空间中相同年龄所有的对象大小的综合和大于survivor空间的一半,
年级大于或等于该年级的对象就可以直接进入老年代
以上采用分代垃圾收集的思想,对一个对象从存活到死亡所经历的历程。期间,在新生代的时刻,会用到复制算法,在老年代时,有可能会用到标记-清楚算法(mark-sweep)算法或者标记-整理算法,这些都是垃圾回收算法基于不同区域的实现,我们看下这几种回收算法的实现原理
四. 垃圾回收算法
4.1 标记清除法
标记清除法是垃圾回收算法的思想基础。标记清除算法将垃圾分为两个阶段:标记阶段和清除阶段。
标记阶段,通过根节点,标记所有从根节点开始的可达对象,未标记过的对象就是未被引用的垃圾对象。清除阶段,清除所有未被标记的对象
4.2 复制算法 Copying
复制算法是,将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在适用的内存中存活对象复制到未使用的内存块,然后清除使用的内存块中所有的对象。
4.3 标记压缩算法(Mark-Compact)
标记压缩算法是一种老年代的回收算法。
标记阶段和标记清除算法一致,对可达对象做一次标记。
清理阶段,为了避免内存碎片产生,将所有的存活对象压缩到内存的一端
五. 垃圾收集器
5.1 概述
垃圾收集器是内存回收的具体实现,不同的厂商提供的垃圾收集器有很大的差别,一般的垃圾收集器都会作用于不同的分代,需要搭配使用。以下是各种垃圾收集器的组合方式
5.2 各种组合的优缺点
猜你喜欢LIKE
相关推荐HOT
更多>>算法评测标准---空间复杂度是什么?
算法评测标准---空间复杂度是什么?空间复杂度是什么?一. 空间复杂度的概念,复杂度(Space Complexity),是对一个算法在运行过程中临时占用存...详情>>
2023-03-23 20:15:04怎么用css画三角形?
怎么用css画三角形?border这里的像素值 和 border-left这里的像素值可以是不一样的,也可以是一样的,根据三角形的形状来进行具体设置值即可,要...详情>>
2023-03-23 15:27:16Maven集成 tomcat插件及使用教程
在实际的项目开发中,特别是分布式项目,往往有N多个子项目需要同时启动测试。这样多个项目引用tomcat插件,配置不同的端口,就可以同时启动N个...详情>>
2023-02-23 14:44:00扫盲CSS中常见的单位
Px是pixel的简写, 被称之为像素单位, px可以在计算机屏幕上,能达到预期的效果,在打印机和其它的高分辨率设备上,它又能取得所希望的效果, 一...详情>>
2023-02-16 13:47:00热门推荐
java变量的作用域是什么?
沸什么是Java循环?
热switch语句的case和default有顺序吗?
热SpringBoot中使用redis 新手入门
新vue的watch和computed的区别以及特点是什么?
算法评测标准---空间复杂度是什么?
Spring整合Junit框架是什么?
break和continue必须要在循环中使用吗?
怎么用css画三角形?
手把手教你搭建Oauth2授权服务!
为什么不能用break?
什么是foreach循环?它有哪些优点和局限性?
react生命周期?16版本删除了什么钩子函数?为什么删除?
经典面试题:static加载机制你知道吗?