| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> Java面试基础篇---CG垃圾回收机制(一万字最终总结) -> 正文阅读 |
|
[Java知识库]Java面试基础篇---CG垃圾回收机制(一万字最终总结) |
本文章参考学习相关文章: https://www.zhihu.com/question/21539353 垃圾回收机制垃圾回收(Garbage Collection,GC)。 以下是这篇文章的大纲: 一、如何判断Java判断一个对象是否是垃圾,使用的有两种方法:引用计数法(reference-counting)和可达性分析法(GC Roots Tracing) 1、引用计数法引用计数法:每一个对象都有一个引用计数器,当这个对象被引用了一次以后,这个计数器就会 +1,当取消这个对象的一次引用以后,这个计数器就会 -1,当引用计数器的值为0 的时候,就代表这个对象失去了价值,就可以被判断是垃圾,就可以被CG垃圾回收机制处理。 但是这个算法会出现内存泄漏的问题。 这里我们通过代码来说明:
在网上很多文章都会告诉各位,以上的代码采用引用计数器的方式来进行处理的时候,由于gcObj1 和gcObj2 指向的对象已经不可以再被访问了,但是又在彼此引用着对方,这样导致即使对象不可以再被访问了,那么它的引用计数器还是不为0 ,从而不能被GC,但是这样说是很难理解的,下面我来通过JVM内存模型详细的解释这个现象出现的原因。 然后接下来程序将虚拟机栈和堆之间的引用给切断了,就出现了下面的这种情况: 此时两个对象的程序计数器的数值为1 ,不符合引用计数法的垃圾回收的条件,但是这个时候两个对象在虚拟机栈中的引用已经不能在访问堆中的具体对象,那这个对象就失去了意义,但是却不能被垃圾回收所处理,便产生了内存泄漏问题。 2、可达性分析法目前主流的虚拟机都是使用的可达性分析算法。这个算法的核心就是以GC Roots对象作为起始点,根据数学中的图论为判断基础,图中的可达起始点的对象便是存活对象,而不可达对象则是需要回收的垃圾内存。这里有两个新的概念,,一个是CG Roots对象 ,另一个是可达性。下面就这两个概念来进行阐述。 什么是CG Roots对象?
什么是可达性?
这里还是用图来进行说明:
所以以上的对象都是存活对象,不可以被垃圾回收机制所回收, 二、如何处理?在确定了哪些对象是垃圾,而可以被回收以后,如何进行高效的回收就成了接下来要考虑的问题。
1、Mark-Sweep(标记-清除)算法这个算法是最简单的算法,最容易实现。具体的步骤分为两个阶段:标记阶段和清除阶段。 下图中的红色区域就是被标记的对象,在下一次的垃圾回收的时候会将红色的标记对象直接清除。
2、Copying(复制)算法为了解决Mark-Sweep(标记-清除)算法的缺陷,复制算法应运而生 3、当B区域使用完毕以后,会把B中的存活对象复制到A中 4、清理B中的所有对象 这种方法是解决了上述的内存碎片问题,但是这个代价又太大,会浪费50%的内存空间,所以这种算法也只是存在于理论中,不具备可用性,一般使用的是优化后的复制算法。 3、Mark-Compact(标记-整理)算法为了解决上面的内存浪费严重和存在大量内存碎片的问题,有出现了标记整理-算法,这种算法的主要思想是:首先是标记出存活的对象,然后将存活的对象按照内存地址移动到内存的一端,最后清除剩下区域中的所有对象。
优点: 为了解决上述的诸多问题,接下了JVM使用了最厉害的处理方法,分代收集算法。 4、Generational Collection(分代收集)算法分代收集算法将GC分为两种,一种是Minor GC (新生代GC),另一种是Full GC(老年代GC,也称为Major GC)
新生代:老年代在堆空间中初始的比例为1:2 (1) 新生代新生代分为两个区域:Eden 区(伊甸园区)和 Survivor区(幸存者区),而 Survivor区又别分为两个部分 from区 和 to区 ,而to和from两个区域不是固定的,会根据垃圾回收的次数进行来回的替换,接下来用图来解释: 接下来我们来看一下在新生代中的垃圾回收的具体过程,在这直接首先要了解一个新的概念:对象年龄计数器。那么何为对象年龄计数器,具体有什么作用:
接下来就进行新生代CG的过程演示: 当对象创建的时候,会首先进入Eden 区,并且初始的年龄都是0,当Eden区被占满的时候,会触发一次垃圾回收 此时触发新生代垃圾回收,将存活的对象复制进from区,对象年龄计数器+1,并且将Eden区清空 此时Eden区里面继续创建新的对象,当Eden区再次被挤满的时候,再次开始新生代垃圾回收,此时from区中也会出现被标记清除的对象,如图所示: (2)老年代老年代中主要存放生命周期较长的对象 当触发了 Full GC 的时候,通常会伴随着 Minor GC,即对整个堆进行垃圾回收,这便是所谓的 Full GC,严格来说的话,Full GC 表示的是对整个堆进行垃圾回收,而 Major GC 是对老年代进行垃圾回收,不过通常情况下 Full GC 和 Major GC 是等价的 Full GC 的速度比 Minor GC 慢的多,一般会慢 10 倍以上,但执行频率低 哪些对象会进入老年代?
针对老年代的对象,不在使用复制算法来进行垃圾的处理,因为老年代没有了“备用仓库”,这里使用的算法就是之前提到的标记-整理或者标记-清除算法。老年代的存活时间很长,因此使用这种算法虽然会消耗大量的时间,但是由于Full GC的频率比较低,所以不会有太大的影响。
注意,在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量和无用的类。这里我们不做太多的解释。 三、拿什么处理?垃圾收集算法是 内存回收的理论基础,而垃圾收集器就是内存回收的具体实现。下面介绍一下HotSpot虚拟机提供的几种垃圾收集器。
2.ParNew
3.Parallel Scavenge
4.Parallel Old
5.CMS
6.G1
以上就是我对Java垃圾回收机制的理解和总结,有不对的地方欢迎提出来,我会加以改正。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 10:49:09- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |