首页 > 科技 >

深入理解Java垃圾回收机制

2019-07-30 00:17:05 暂无 阅读:837 评论:0

一、垃圾收受机制的意义

垃圾收受能够有效的防止内存泄露,有效的使用余暇的内存;

内存泄露: 指该内存空间使用完毕后未收受,在不涉及复杂数据构造的一样情形下,Java的内存泄露示意为一个内存对象的声明周期超出了法式需要它的时间长度。

二、垃圾收受机制的算法

Java说话规范没有明确的解说JVM使用哪种垃圾收受算法,然则任何一种垃圾收受算法一样要做两件根基事情:(1)发现无用的信息对象;(2)收受将无用对象占用的内存空间。使该空间可被法式再次使用。

1、引用计数法

引用计数算法是早期策略,在这种方式中,堆中的每个对象实例都有一个引用计数器,当一个对象被建立时,且该对象实例分派给一个变量,该变量计数设置为1,当任何其他变量赋值给这个对象引用时,计数加1,但当一个对象实例的某个引用跨越了生命周期或许被设置为一个新值时,对象实例的引用计数器减1,任何引用计数器为0的对象实例能够当做垃圾收受集。当一个对象的实例被垃圾收集时,它的引用的任何对象实例计数器减1.

这种算法的长处是能够被很快的执行,交错在法式运行中。对法式需要不被长时间打断的实时情况中有利。瑕玷就是无法检测出轮回引用。如父类对象有一个对子类对象的引用,子类对象反过来引用父类对象。如许,他们的引用计数永远不愿能为0.

2、tracing算法或标记消灭算法

深入理解Java垃圾回收机制

根搜刮算法是从离散数学的图论中引入的,法式把所有的引用关系看做一张图,从一个节点GC ROOT起头,寻找对应的引用节点,找到这个节点后,持续寻找这个节点的引用节点,当所有的引用节点寻找完毕后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。

Java中可作为GC Root的对象有

1、虚拟机栈中引用的对象

2、方式区中的静态属性引用的对象

3、方式区中常量引用的对象

4、内陆方式栈中引用的对象。

标记消灭算法采用从根鸠合进行扫描,对存活的对象进行标记,标记完毕后,再扫码整个空间中未被标记的对象,进行收受。

3、compacting算法或标记整顿算法

标记整顿算法采用标记消灭算法一般的体式进行对象的标记,但在消灭时分歧,在收受不存活的对象占用的空间后,会将所有的存活对象往左端余暇空间移动,并更新对应的指针。标记-整顿算法是在标记-消灭算法的根蒂上,又进行了对象的移动,是以成本更高,然则却解决了内存碎片的问题。在基于Compacting算法的收集器的实现中,一样增加句柄和句柄表。

三、Java有了GC同样会显现内存泄露问题

1.静态鸠合类像HashMap、Vector等的使用最轻易显现内存泄露,这些静态变量的生命周期和应用法式一致,所有的对象Object也不克被释放,因为他们也将一向被Vector等应用着。Static Vector v = new Vector();

for (int i = 1; i<100; i++)

{

Object o = new Object();

v.add(o);

o = null;

}

在这个例子中,代码栈中存在Vector 对象的引用 v 和 Object 对象的引用 o 。在 For 轮回中,我们络续的生成新的对象,然后将其添加到 Vector 对象中,之后将 o 引用置空。问题是当 o 引用被置空后,若是发生 GC,我们建立的 Object 对象是否可以被 GC 收受呢?谜底是否认的。因为, GC 在跟踪代码栈中的引用时,会发现 v 引用,而持续往下跟踪,就会发现 v 引用指向的内存空间中又存在指向 Object 对象的引用。也就是说尽管o 引用已经被置空,然则 Object 对象仍然存在其他的引用,是能够被接见到的,所以 GC 无法将其释放掉。若是在此轮回之后, Object 对象对法式已经没有任何感化,那么我们就认为此 Java 法式发生了内存泄露。

2.各类保持,数据库保持,收集保持,IO保持等没有显露挪用close封闭,不被GC收受导致内存泄露。

3.监听器的使用,在释放对象的同时没有响应删除监听器的时候也或者导致内存泄露。

相关文章