Effective Java Item7:Avoid Finalizers,解说为什么finalize是不安全的,不主张运用ITeye - 凯时娱乐

Effective Java Item7:Avoid Finalizers,解说为什么finalize是不安全的,不主张运用ITeye

2019-01-13 05:47:47 | 作者: 冰夏 | 标签: 目标,创立,收回 | 浏览: 1958

运转这段代码,很快就会呈现堆外内存溢出。为什么呢?就是由于RevisedObjectInHeap.finalize办法不能及时履行,不能及时开释堆外内存。能够参阅我的另一篇博客:java中运用堆外内存,关于内存收回需求留意的事和没有解决的遗留问题

 

当然运用finalize还有其他问题,详细的能够参阅《Effective Java》。接下来介绍下JVM履行finalize办法的一些理论知识。完成了finalize()的目标,创立和收回的进程都更耗时。创立时,会新建一个额定的Finalizer 目标指向新创立的目标。 而收回时,至少需求通过两次GC。

 

先来看下新建目标的时分发作的事,测验进程如下:

1、在TestObjectNoFinalize和TestObjectHasFinalize这2个类的while循环中打上断点,在java.lang.ref.Finalizer的Finalizer()和register()打上断点

2、别离debug运转TestObjectNoFinalize和TestObjectHasFinalize,调查进入Finalizer断点的次数


测验成果如下:

1、TestObjectNoFinalize没有finalize()办法

      进入Finalizer断点的次数很少(3次,指向的是JarFile、Inflater、FileInputStream),之后进入while循环中的断点,不会再进入Finalizer中的断点。也就是说:创立TestObjectNoFinalize目标的时分,不会创立相应的Finalizer目标。

2、TestObjectHasFinalize供给了finalize()办法

      每次创立TestObjectHasFinalize目标的时分,都会创立相应的Finalizer目标指向它。


再看下收回目标的时分发作的事:加上-XX:+PrintGCDetails参数,调查下废物收回的进程。



能够看到TestObjectNoFinalize中都是在新生代中发作时的废物收回,很快就收回掉了内存。


TestObjectHasFinalize进行了几回新生代内存收回之后,频频的进行[Full GC。这是认为收回内存的速度太慢,导致新生代内存不能及时开释,所以有必要进行Full GC以希望获取闲暇的内存空间。这个试验尽管不能直接证明至少需求进行2次GC,可是能够清楚的看到:含有finalize()的目标废物收回速度会很慢。

 

finalize机制的一些总结:

1、假如一个类A完成了finalize()办法,那么每次创立A类目标的时分,都会多创立一个Finalizer目标(指向刚刚新建的目标);假如类没有完成finalize()办法,那么不会创立额定的Finalizer目标

2、Finalizer内部保护了一个unfinalized链表,每次创立的Finalizer目标都会刺进到该链表中。源码如下

 

版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表凯时娱乐立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章