java垃圾回收机制

JVM垃圾回收机制

    提到Java垃圾回收机制就不得不提到一个方法:

    system.gc()用于调用垃圾收集器,在调用时垃圾收集器将运行以回收未使用的内存空间,它将尝试释放被丢弃对象所占用的空间。

作为程序员有必要了解gc方法,这也是在面试中经常会被问及的问题:

我们从三个方面来理解gc:

1.JVM如何确定哪些空间能被回收?

2.JVM会在什么时候进行垃圾清除的动作?

3.JVM如何清除垃圾的?

1.JVM如何确定哪些空间能被回收

通过两个算法:

1.引用计数算法

简单的来说就是判断对象的引用数量。实现方式:给对象共添加一个引用计数器,每当有引用对他进行引用时,计数器的值就加1,当引用失效,也就是不在执行此对象是,他的计数器的值就减1,若某一个对象的计数器的值为0,那么表示这个对象没有人对他进行引用,也就是意味着是一个失效的垃圾对象,就会被gc进行回收。但是这种简单的算法在当前的jvm中并没有采用,原因是他并不能解决对象之间循环引用的问题。假设有A和B两个对象之间互相引用,也就是说A对象中的一个属性是B,B中的一个属性时A,这种情况下由于他们的相互引用,从而是垃圾回收机制无法识别。

2.可达性分析算法

因为引用计数法的缺点有引入了可达性分析算法,通过判断对象的引用链是否可达来决定对象是否可以被回收。可达性分析算法是从离散数学中的图论引入的,程序把所有的引用关系看作一张图,通过一系列的名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连(就是从 GC Roots 到这个对象不可达)时,则证明此对象是不可用的。

2.JVM会在什么时候进行垃圾清除的动作


    会在cpu空闲的时候自动进行回收;

    在堆内存存储满了之后;

    主动调用System.gc()后尝试进行回收(不一定成功)。

3.JVM如何清除垃圾的?

通过四个算法:

标记-清除算法:

    先标记所有需要回收的对象,然后清除标记的对象

缺点:会产生空间碎片,资源浪费

复制算法

    将内存分为两块,当使用的一块满了就将存活对象 复制到另一块中,再将使用的那一块清空

缺点:内存缩小约为原来的一半

标记-整理算法

    先标记所有需要回收的对象,然后清除标记的对象,再将剩下的存活对象整理,避免了空间碎片的产生

分代收集算法


    分代收集算法是比较智能的垃圾回收算法,也是现在JVM使用最多的算法,他本身其实并不算是一种算法,而是会在具体的场景上选择上面三种方法来进行垃圾回收

“代”指的是新生代、老年代、永久代

新生代

    按8:1:1分为 eden、survivorl0、survivor1三个区域。

一般情况下所有新生成的对象都存放于新生代。

在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法。只需要付出少量存活对象 的复制成本就可以完成收集。

老年代

    老年代中存放的一般都是生存周期比较长的对象。

老年代中因为对象存活率高、没有额外空间对他进行分配担保,就必须用标记-清除或者标记-整理。

永久代

    主要用来存放静态文件。

在jdk8的时候Java废弃了永久代,同时提供了与永久代类似的叫做“元空间”的技术。元空间的本质和永久代类似。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。也就是不局限于jvm可以使用系统的内存。理论上取决于32位/64位系统可虚拟的内存大小。

你可能感兴趣的:(java垃圾回收机制)