【Java编程思想】finalize方法的真正用途?


前言

话说在最前面:finalize方法的用途有两个:1.finalize()方法释放本地方法申请的内存;2.作为终结条件

Java中有垃圾回收,可以对new出来且不再使用的对象进行回收,
但是Java中有些情况下,申请内存不同通过new进行的!这种情况下垃圾回收就无法进行内存回收了
这种时候finalize()方法就会发挥它的作用,对这部分特殊申请的内存进行内存回收处理!


了解finalize之前需要知道三点

  1. Java中的对象不想C++中的对象,是可能不被垃圾回收的;(如果C++的代码没问题,申请的内存是一定要释放的,但是Java中的对象如果没达到条件,是不会被GC的)
  2. Java中的垃圾回收不等于C++中的析构函数;(Java并没有提供相关析构函数的概念,垃圾是自动回收的,不需要手动创建一个执行清理工作的方法)
  3. 垃圾回收只与内存有关;(Java中的垃圾回收只针对不再使用的内存,因此垃圾回收的任何行为(以及finalize方法)都必须只跟内存回收有关)

(用途1)finalize()方法释放本地方法申请的内存

  • finalize方法涉及到一种特殊的申请对象存储空间的方式(并不是一般的通过new来申请)。
  • 这种情况发生在Java中使用本地方法的时候(因为本地方法使用的是C或者C++来实现的),在本地方法中,C语言会调用malloc()函数来申请分配存储空间,而且除非调用了free()函数,不然是不会释放内存空间的(会导致内存泄漏)。
  • 因此在finalize()方法中进行调用了本地方法中的(C语言的)free()方法释放了malloc申请的内存空间。

gc和finalize都不保证一定发生

  • 在C++中,如果创建了一个局部对象,那么这个局部对象会存储在栈中,跟随方法的结束而销毁;C++如果通过new来创建对象,当使用结束的时候需要通过delete方法来调用析构函数,来讲new出来的内存空间释放掉,不过没有delete方法,那么析构函数永远不会被调用,那么就导致了内存泄漏。
  • 相反,Java中首先没有局部对象的概念,在HotSpot虚拟机中没有栈上分配的概念,因此对象都是在堆中通过new的方式申请的内存;其次Java中没有析构函数和delete的概念,但是Java有GC垃圾回收器。这样的话就比较方便了,GC会在Java运行时内存面临耗尽的情况下,对内存空间进行垃圾回收或者finalize。
  • 这样也就说明了,垃圾回收和finalize并不是一定能发生的,如果内存状况良好,或者没有垃圾,就可能不发生gc和finalize

(用途2)finalize作为终结条件

  • finalize方法绝对不可以直接调用,因此可能使用finalize方法的情景就少了,但是finalize还有别的用处!
  • 也就是将finalize方法当做对象的终结条件,进行验证!
  • 举个例子,一个对象如果我们不使用了,我们希望的是它能够被gc掉,但是可能这个对象中会存在一些调用,导致这个对象并不能被当做垃圾顺利的gc掉,太多的话会导致内存在漏严重,并且往往这些代码上的缺陷非常的难发现,这个时候就可以使用finalize方法来发现这种现象是否存在。
  • 尽管finalize方法不能被显式的调用,但是我们能够通过finalize方法作为检查对象终结的条件,发现代码上的缺陷,找到问题所在!这个用法很关键!

举个代码上的例子:

  • 假设每个被new出来的Solution对象被垃圾回收的终结条件是:status为false;(说人话就是对象的status为false才会被gc,如果为true的话就不会被gc)
  • 在mian方法中,new了两个对象,其中一个将status改为了false,但是另一个假如忘记修改状态了。
  • 这个时候finalize作为终结条件,就可以发现这个问题(发现要gc的对象没有更改状态,并打印)(如下代码所示)
class Solution {
    boolean status = false;

    public Solution(boolean status) {
        this.status = status;
    }

    public void setStatusFalse(){
        this.status = false;
    }

	//这里重写了finalize方法
    @Override
    protected void finalize() throws Throwable {
        if (this.status){
            System.out.println("error:内存泄漏");
        }
    }

    public static void main(String[] args) {
        Solution solution = new Solution(true);
        solution.setStatusFalse();
        new Solution(true); // 忘记更改状态
        System.gc(); //强制进行full gc
    }
}

输出:
在这里插入图片描述
这个时候我们就可以根据打印的输出,检查一下是不是写代码有bug,导致有对象并没有达到终结条件。


【end】

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值