一 谈一谈jvm的垃圾回收机制
1.1 什么是垃圾回收
在正式介绍垃圾回收算法前,先来说说什么是垃圾回收。这里所说的垃圾主要指的是已经不会再继续使用的对象,当然也有可能是其他,比如不再使用的类以及常量,但主要还是指对象,所以以下算法将介绍对象的回收。所以垃圾回收的含义就是:将内存中已经不会被使用的对象(或类和常量)清除,释放内存空间。
JVM的内存模型分为五个部分,其中堆内存的唯一目的就是存放对象,对象也基本上都是存放在堆内存中。堆中,为了方便进行垃圾回收,一般会将内存分为两个部分:
老年代:用来存放生命周期长的对象。新生代中存活了较长时间的对象会被迁移到这里(当然,对象进入老年代不仅仅只有这一个方法),所以这里存放的对象生命周期一般较长,所以这一块区域发生垃圾回收的频率较低,释放的空间也较少;
新生代:用来存放生命周期短的对象。由于这一块内存中的对象存活时间较短,所以频繁发生垃圾回收,而且每次回收一般都能释放大量空间;
下面正式开始讨论JVM中的垃圾回收算法。
1.2 识别垃圾的方式
(1) 引用计数法
引用计数法就是通过引用来识别无用对象。我们记录每一个对象的引用个数,若有新的变量引用一个对象时,这个对象的引用个数加1;若一个引用失效时,引用的个数减1,而引用个数为0的对象,即可作为垃圾被回收。这里要注意,若这些垃圾对象的成员变量引用了其他对象,则当垃圾对象被释放时,它的这个引用自然就失效了。
这个算法实现简单,效率也高,但是,它并没有被用在主流的Java虚拟机中,因为它有一个很大的缺陷——很难解决循环引用的问题
(2)可达性分析法
可达性分析法是Java垃圾回收中判别无用对象的主要方法。这个方法的步骤是,从根节点对象出发,使用DFS或BFS算法,沿着引用递归遍历,而无法被遍历到的对象,就是无法再被使用的对象,可以被垃圾回收器回收。所谓的根节点,就是我们能够直接使用的引用类型变量,如:
1)方法中的参数或局部变量;
2)类的静态成员或非静态成员;
3)代码中的常量;
这种方法的效率相对于引用计数来说相对复杂,而且效率较低,但是解决了循环引用的问题,是Java垃圾回收中主要使用的方法。
关于可达性分析可以看一看这位大佬写的:java可达性分析详解
1.3 如何释放垃圾
释放垃圾指的就是清除无用对象,释放它们所占的内存空间,方便继续使用。这里主要介绍三种方法:
1:标记—清除算法;
2:复制算法;
3:标记—整理算法;
这三种算法根据具体情况的不同,搭配使用,才能发挥最好的效果。这些东西我收集了比较好的解答。
标记-清除算法推荐阅读:
复制算法具体解析;
标记—整理算法;
4分代收集算法
分代收集算法并不是什么新思想,而是对上面三种算法的综合使用。前面也提过,为方便垃圾回收,一般将堆内存分为新生代和老年代两个部分。
对于新生代而言,这一块区域中的对象存活时间短,每一次垃圾回收都能回收大部分内存,所以适合使用复制算法,同时以老年代作为这个算法的担保空间;
对于老年代而言,每次垃圾回收只能释放小部分空间,若使用复制算法,每次将需要做大量复制,而且此时Survivor需要较大的空间,所以不适合使用复制算法,因此在老年代中,一般使用标记—清除或者标记—整理算法;
讲解的比较清除:深入理解JVM------分代收集算法
1.3 完结
以上就是java垃圾回收机制流程.