在java中为什么不推荐使用finalize,看到这个原因你也不会用了

在java中为什么不推荐使用finalize,看到这个原因你也不会用了




java提供了一个finalize方法,可以帮助我们进行资源释放,类似于C++中的析构函数。但是目前普遍的认识是不要使用,为什么呢?就是因为对java虚拟机的垃圾回收有影响。这篇文章对其进行一个说明。

一、为什么有影响

我们都知道一个对象如果没有了任何引用,java虚拟机就认为这个对象没什么用了,就会对其进行垃圾回收,但是如果这个对象包含了finalize函数,性质就不一样了。怎么不一样了呢?

java虚拟机在进行垃圾回收的时候,一看到这个对象类含有finalize函数,就把这个函数交给FinalizerThread处理,而包含了这个finalize的对象就会被添加到FinalizerThread的执行队列,并使用一个链表,把这些包含了finalize的对象串起来。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aCQuqN8P-1611574075333)(https://pics5.baidu.com/feed/1e30e924b899a9010d34c78331bb0d7d0208f532.jpeg?token=cc6b19d8b9ecf5e0697042b70da81e1d&s=0D40EC12E18768EA584DA0CE0200D0A1#pic_center)]

他的影响在于只要finalize没有执行,那么这些对象就会一直存在堆区,不过这里只是4个包含了finalize的对象,影响不是那么大,如果有一万个或者是十万个呢?这就影响大了。

finalize的原理其实很简单,在这里简要的梳理一下:

(1)对象在初始化的过程中会判断是否重写了finalize,方法是判断两个字段标志has_finalizer_flag和RegisterFinalizersAtInit。

(2)如果重写了finalize,那就把当前对象注册到FinalizerThread的ReferenceQueue队列中。注册之后的对象就叫做Finalizer。方法是调用register_finalizer函数。此时java虚拟机一看当前有这个对象的引用,于是就不进行垃圾回收了。

(3)对象开始被调用,FinalizerThread线程负责从ReferenceQueue队列中获取Finalizer对象。开始执行finalize方法,在执行之前,这个对象一直在堆中。

(4)对象执行完毕之后,将这个Finalizer对象从队列中移除,java虚拟机一看对象没有引用了,就进行垃圾回收了。

这就是整个过程。不过在这里我们主要看的是finalize方法对垃圾回收的影响,其实就是在第三步,也就是这个对象含有finalize,进入了队列但一直没有被调用的这段时间,会一直占用内存。

我们使用一个案例来分析一波:

二、案例演示

我们创建一个类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DfNduGe8-1611573918607)(https://pics7.baidu.com/feed/91529822720e0cf38d0cc8e32668f519bf09aae7.jpeg?token=4734acc223620567aa8a2749678d55b4&s=B8C1A1441AE48D6C1645FC0D0200E0C1)]

现在创建了类,我们设置以下参数。

在这里插入图片描述

在main方法中,创建了1000个Fdd对象,如果不执行finalize方法,那么因为没有调用所以会进行垃圾回收,此时不断我们创建多少个,都不会出现任何问题。但是如果存在finalize方法,就不一样了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U4A65F8f-1611573918610)(https://pics5.baidu.com/feed/8326cffc1e178a82bc5580dada2d748ba977e817.jpeg?token=3fbaf4c915d5bbe826a4f5b2ee97de54&s=B2D7A5645BE191680C594C0F0000A0C1)]

我们看到每个对象都会执行finalize,在执行之前的这段时间一直会在堆区,执行完了就会被清理,所以你看到这里执行了不少于5次的finalize方法。但是对象一旦超出了我们设置的5M,就会出现内存溢出。一句话总结就是出现了对象堆积。现在使用MAT工具来分析一下。

Mat工具是一个插件,也可以自己下载一个。下载完成之后打开我们刚刚生成的a.dump即可。

下面这张图就是分析的结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I8V4gHt0-1611573918612)(https://pics4.baidu.com/feed/5fdf8db1cb134954eadbae82145c9a5ed0094a23.jpeg?token=06acb154fac65193a374ab05ae8848bc&s=48803C72002657075D93615F0200F0E2)]

a这块的内容就是Finalizer,也就是我们的Fdd对象,b包含的比较多,乱七八糟的剩余信息。当然你也可以查看一些其他的信息。都在MAT工具上。还有一些正在执行的finalizer和准备执行的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jEQXgWtC-1611573918613)(https://pics2.baidu.com/feed/574e9258d109b3deadf695b0e6916b87810a4c54.jpeg?token=003ee56e52cd0aab8cc542e15fa7c7d0&s=C343DD1A191FD0CE1A7174DA030090B2)]

OK,一些其他的信息就不再展示了。








                                           转载于@愚公要移山1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值