温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

有哪些Java GC的相关问题

发布时间:2021-11-02 09:18:38 来源:亿速云 阅读:130 作者:iii 栏目:编程语言

这篇文章主要介绍“有哪些Java GC的相关问题”,在日常操作中,相信很多人在有哪些Java GC的相关问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”有哪些Java GC的相关问题”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

Java GC

目标

遇到一个问题或者一个知识点,我们要理解和明白是要解决什么问题的。说到 Java GC 那这个 GC  的目的是什么呢?很显然是回收内存,因为内存是有限的,随着程序中创建的对象越来越多,如果进行回收就会导致内存越来越大,最后程序就会出现异常。既然目的是为了回收内存,那么新的问题来了,哪些对象可以被回收呢?什么时候进行回收呢?怎么回收呢?

哪些对象可以被回收

简单来说就是无用的对象可以被回收,那么换句话说,如果定义一个对象是无用的呢?这里主要有两种方法,一个叫引用计数法,一个叫可达性分析法。

引用计数

引用计数说的是如果一个对象被别的对象进行了一次引用,那么该对象会有一个引用计数器,这个计数器就会加一;如果被释放一下,引用计数器就会减一。当引用计数器的计数为  0 的时候就表示这个对象是无用的,此时就可以对这样对象进行回收了。表面上看好像挺合理的,实现起来也很方便,但是仔细一想就会发现有问题。既循环引用的问题,比如对象  A 引用了对象 B,但是对象 B 当中也引用了对象 A,那么这个时候对象 A 和对象 B 的引用计数器的计数都不会是  0,但是这两个对象都没有被其他对象引用,理论上来说这两个对象都是可以被回收的。

从上面看到,这种方案是有问题的会导致内存泄露。随之而来的就出现了另一种方案,可就是可达性分析。

可达性分析

可达性分析说的是从 GCRoots 的点作为起点,向下搜索,当找不到任何引用链的时候表示该对象为垃圾对象。那么哪些对象可以被认为是 Roots 节点呢?有  Java 栈中的对象,方法区的静态属性和常量以及本地方法栈中的对象。从这几种对象依次向下搜索,如果没有能达到 Roots  节点的对象就是垃圾对象,就说明可以被回收。

如下图所有,对象 A,B,C都能找到与 Roots 节点的联系,但是对象 D,E,F 三个并不能找到与 Roots 节点的联系,也就是不可达,所以 DEF  这三个对象就是垃圾对象。

有哪些Java GC的相关问题

什么时候回收

上面的两种方案解决了哪些对象能被回收,那么下个问题,就是什么时候进行垃圾回收呢?在排除人为调用的时候,垃圾回收都是发生在为新生对象进行内存分配的时候,这个时候如果内存空间不足就会触发  GC 进行垃圾回收。

怎么回收

上面我们知道了哪些对象可以被回收,也知道我们应该什么时候进行回收,那下面要解决的就是如何进行垃圾回收了。垃圾回收根据实现的方式不同有多种不同的算法实现。比如有标记清除算法,复制算法,标记整理算法,分代回收算法,下面简单介绍一下,想深入了解的可以自行去研究一下。

标记清除算法

标记清除算法很好理解,主要就是执行两个动作,一个是标记,另一个是对进行标记的对象内存进行清除回收。这个算法有个问题就是会出现内存碎片化严重。如下图所示:

有哪些Java GC的相关问题

从上图中可以看到,在进行内存回收后出现了严重的内存碎片化,这就导致在分配某些大对象的时候仍然会出现内存不够的情况,但是总体内存确是够的。

复制算法

复制算法的实现方式比较简洁明了,就是霸道的把内存分成两部分,在平时使用的时候只用其中的固定一份,在当需要进行 GC  的时候,把存活的对象复制到另一部分中,然后将已经使用的内存全部清理掉。如下图:

有哪些Java GC的相关问题

从上图可以看到解决了标记清除的内存碎片化问题,但是很明显复制算法有另一个问题,那就是内存的使用率大大下降,能使用的内存只有原来的一半了。

标记整理算法

既然标记清除和复制算法各有优缺点,那自然的我们就想到是否可以把这两种算法结合起来,于是就出现了标记整理算法。标记阶段是标记清除算法一样,先标记出需要回收的部分,不过清除阶段不是直接清除,而是把存活的对象往内存的一端进行移动,然后清除剩下的部分。如下图:

有哪些Java GC的相关问题

标记整理的算法虽然可以解决上面两个算法的一些问题,但是还是需要先进行标记,然后进行移动,整个效率还是偏低的。

分代回收算法

分代回收算法是目前使用较多的一种算法,这个不是一个新的算法,只是将内存进行的划分,不同区域的内存使用不同的算法。根据对象的存活时间将内存的划分为新生代和老年代,其中新生代包含  Eden 区和 S0,S1。在新生代中使用是复制算法,在进行对象内存分配的时候只会使用 Eden 和 S0 区,当发生 GC 的时候,会将存活的对象复制到 S1  区,然后循环往复进行复制。当某个对象在进行了 15 次GC  后依旧存活,那这个对象就会进入老年代。老年代因为每次回收的对象都会比较少,因此使用的是标记整理算法。

垃圾回收器

讲完了垃圾回收算法,我们再看下垃圾回收器,每一种垃圾回收器都是不同时代的不同产物,都有其独特性。

  • Serial 垃圾收集器(单线程、复制算法)

  • ParNew垃圾收集器(Serial+多线程)

  • Parallel Scavenge 收集器(多线程复制算法、高效)

  • SerialOld收集器(单线程标记整理算法)

  • ParallelOld收集器(多线程标记整理算法)

  • CMS收集器(多线程标记清除算法)

  • G1收集器

各个垃圾收集器的配合使用情况可以参考下图,个人觉得对这么多的收集器没有必要全部精通,可以注重关注一下 CMS 和 G1  就可以了。感兴趣的小伙伴可以自己的研究一下。

有哪些Java GC的相关问题

到此,关于“有哪些Java GC的相关问题”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI