简书:capo 转载请注明原创出处,谢谢!

前言:

今天我们来看看Object中一个经常被人遗忘的方法,finalize方法。老规矩,我们先看看Javadoc是怎样描述这个方法的

/**

* Called by the garbage collector on an object when garbage collection

* determines that there are no more references to the object.

* A subclass overrides the {@code finalize} method to dispose of

* system resources or to perform other cleanup.

*

* The general contract of {@code finalize} -is that it is invoked

* if and when the Java™ virtual

* machine has determined that there is no longer any

* means by which this object can be accessed by any thread that has

* not yet died, except as a result of an action taken by the

* finalization of some other object or class which is ready to be

* finalized. The {@code finalize} method may take any action, including

* making this object available again to other threads; the usual purpose

* of {@code finalize}, however, is to perform cleanup actions before

* the object is irrevocably discarded. For example, the finalize method

* for an object that represents an input/output connection might perform

* explicit I/O transactions to break the connection before the object is

* permanently discarded.

*

* The {@code finalize} method of class {@code Object} performs no

* special action; it simply returns normally. Subclasses of

* {@code Object} may override this definition.

*

* The Java programming language does not guarantee which thread will

* invoke the {@code finalize} method for any given object. It is

* guaranteed, however, that the thread that invokes finalize will not

* be holding any user-visible synchronization locks when finalize is

* invoked. If an uncaught exception is thrown by the finalize method,

* the exception is ignored and finalization of that object terminates.

*

* After the {@code finalize} method has been invoked for an object, no

* further action is taken until the Java virtual machine has again

* determined that there is no longer any means by which this object can

* be accessed by any thread that has not yet died, including possible

* actions by other objects or classes which are ready to be finalized,

* at which point the object may be discarded.

*

* The {@code finalize} method is never invoked more than once by a Java

* virtual machine for any given object.

*

* Any exception thrown by the {@code finalize} method causes

* the finalization of this object to be halted, but is otherwise

* ignored.

*

* @throws Throwable the {@code Exception} raised by this method

* @see java.lang.ref.WeakReference

* @see java.lang.ref.PhantomReference

* @jls 12.6 Finalization of Class Instances

*/

protected void finalize() throws Throwable { }

梳理一下上面规范讲述的几点

访问垃圾收集在对象上当垃圾收集这确定这个对象上没有更多的引用时可能会触发finalize方法

一个子类重写了finalize方法处理系统资源或者执行其它的清理也就是调用System.gc可能会触发

这个一般的合约规定finalize,如果Java虚拟机已经确定这不再有任何意味这个对象能通过任何一个尚未死亡的线程访问的方法调用,除非是由于最后确定的其它对象或类的准备工作所采取的行动.

finalize方法可以采取任何行动,包括使此对象再次可用于其它线程,finalize的通常是在对象不可撤销地丢弃之前执行清楚动作.例如:表示输入输出连接的对象的finalize方法可能会在对象被永久丢弃之前执行显式I/O事务来中断连接

Object中finalize操作只是返回一个正常线程

Java规范确保调用finalize的线程在调用finalize方法时不会持有任何用户可见的同步锁

如果finalize方法抛出未捕获的异常,则会忽略该异常,并终止该对象的定类。

finalize方法不会被任何对象调用多次

finalize方法抛出的任何异常都会导致该对象的终止被停止,否则就忽略

针对上述规范,我有以下几点疑惑

finalize到底是使用在什么应用场景

通常我们知道对象创建完,要做清理操作,当然GC会清理哪些由new分配的内存,但是如果不是通过new分配的内存清理的话,就需要调用finalize方法.

它的工作原理:一旦垃圾回收器准备释放对象占用的内存空间,将首先调用finalize方法,并且在下一次垃圾回收动作发生,才会真正的回收该对象占用的内存,也就是finalize方法会在垃圾回收器真正回收对象之前调用

finalize到底是不是C++中的析构函数

在C++中销毁对象必须用到析构函数,且兑现一定会被销毁(如果程序没有缺陷),但是Java里的对象并非总是被回收.也就是:

对象有可能没有被垃圾回收

垃圾回收并不是等于析构(因为析构一定会销毁对象)

我们使用finalize这个方法有时候是为了确保某个对象已经被清楚,我们自己手动的去清除这个对象.

一般只要程序没有濒临储存空间用完的那一刻,对象占用的存储空间就总也得不到释放.如果这个程序结束了,垃圾回收器一直没有释放掉你创建的任何对象的存储空间,则随着程序的退出,那些资源也会全部交还给操作系统.个人觉得这个操作策略是正确的,能不用垃圾回收去处理就不出来,毕竟就省去了这部分开销。

所以finalize并不会确保对象会被销毁,它不是析构函数.

finalize另外一个用途(判断对象在清理时是否安全释放)

前面已经说过它可能是用来清理一些不是用过new创建的内存对象,那么这些对象就是指的是Java中的本地方法创建的对象

无论是垃圾回收还是终结方法(finalize)都不能不保证一定会发生,因为它们发生的条件是对象被回收(这个条件是比较苛刻的,JVM只有在濒临内存耗尽的情况下才会触发)

finalize可能会用于对象终结条件的验证:

我们可以用finaliz来检测对象被清理之前是不是还有什么操作没有执行,比如当某个对象打开了一个文件,在对象被回收之前程序应该关闭这个文件。使用finalize我们可以确保对象对安全的释放掉了.

下面看finalize一个用于检验对相关是否安全释放的例子:

package com;

/**

* Created by XMl on 2017/9/8.

*/

public class Book {

public boolean checkedOut = false;

public Book(boolean checkedOut) {

// checkedOut = checkedOut;

this.checkedOut = checkedOut;

}

public void checkIn() {

checkedOut = false;

}

/**

* 重写finalize方法

*

* @throws Throwable

*/

@Override

protected void finalize() throws Throwable {

//校验checkedOut

if (checkedOut) {

System.out.println("校验出现了一次错误: Checked out ");

}

// super.finalize();

}

}

我们写一测试类

package com.rtti.xml;

import com.Book;

/**

* Created by XMl on 2017/9/8.

*/

public class TerminationCondition {

public static void main(String[] args) {

Book novel = new Book(true);

novel.checkIn();

//对checked进行了一次误操作

new Book(true);

//调用Gc 强制执行终结操作(finalize)

System.gc();

}

}

打印信息:

image.png

我们看到输出校验信息.但是我们调用System.gc的时候并没有回收对象内存

总结:

垃圾回收内存是JVM的一个不确定操作,通常会在系统濒临内存溢出可能会回收,所以你不要指望垃圾回收来控制finalize方法的调用

finalize方法通常是用于清理一些非本地方法(native),和一些对象安全释放校验的操作

finalize java,Java中Object对象finalize方法详细解析相关推荐

  1. JavaScript中Object对象方法超详细讲解举例说明仅此一篇

    JavaScript中Object对象方法超详细讲解举例说明仅此一篇 Object.assign() Object.create() Object.values() Object.entries() ...

  2. java常见log日志的使用方法详细解析

    目录 前言 1. Java.util.Logger 2. org.apache.logging.log4j 2.1 xml配置文件 3. org.slf4j.Logger 前言 log日志可以debu ...

  3. jquery 遍历java对象_jquery中object对象循环遍历的方法

    一个朋友问对象如何转为数组,当我问他为啥要转得时候,他告诉我,数组可以用js循环遍历,而对象则不可以.其实呢,对象同样可以循环遍历的啊.不用转换也可以循环!说明你对js或者jquery的某些操作不是很 ...

  4. java中的request对象_java中request对象各种方法的使用实例分析

    本文实例讲述了java中request对象各种方法的使用.分享给大家供大家参考,具体如下: request对象是从客户端向服务器端发出请求,包括用户提交的信息以及客户端的一些信息.request对象是 ...

  5. java工作中好用的方法

    java工作中好用的方法 1.copyProperties() 复制对象参数的方法,当两个对象中的参数有一部分是一致的时候,用这个方法,不需要一个一个get,set参数了. BeanUtils.cop ...

  6. java 发送短信 多通道_一种Java卡多通道临时对象管理方法与流程

    本发明涉及Java智能卡领域,具体涉及一种Java卡多通道临时对象管理方法. 背景技术: :JavaCard规范支持逻辑通道的概念,允许最多智能卡中的16个应用程序会话同时开启,每个逻辑通道一个会话. ...

  7. 《Android游戏开发详解》一2.18 使用Java API中的对象

    本节书摘来异步社区<Android游戏开发详解>一书中的第2章,第2.18节,译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区"异步社区"公众号查看. 2.1 ...

  8. 【Java 8 新特性】Java 8中的Function.apply方法

    Java 8中的Function.apply方法 参考文献 java.util.function.Function是一个接口,已经在 Java 8中引入. Function是一个函数接口. 因此它可以 ...

  9. java pattern matches,Java正则表达式中的Pattern.matches()方法

    java.util.regex.Pattern.matches()方法匹配正则表达式和给定的输入.它有两个参数,即正则表达式和输入.如果正则表达式和输入匹配,则返回true,否则返回false. 给出 ...

最新文章

  1. python tkinter 滚动条_如何在tkinter窗口中添加滚动条?
  2. 点在多边形内算法,C#判断一个点是否在一个复杂多边形的内部
  3. P1829 [国家集训队]Crash的数字表格(推了好久的mobius反演)
  4. [html] H5页面在微信中如何禁止分享给好友和朋友圈?
  5. 数据结构php语言,PHP语言做网页开发,会用到什么数据结构,算法?
  6. oracle 列 连续,oracle中某列连续相同值的记录数统计(一个简单的例子)
  7. 集群IPtables转发与防火墙
  8. jquery指定节点设css,jquery 获取和设置节点属性 css样式
  9. UITableView总忘记的
  10. 第 19 次 CCF CSP 认证 202006-2 稀疏向量(svector)
  11. java实现菱形的打印java实现菱形的输出
  12. 【安全牛学习笔记】端口扫描
  13. 贴片led正负极判断
  14. 亲测~Win10开启系统自带Wifi热点步骤
  15. HCNE110个知识点
  16. Session的活化与钝化
  17. 数据结构与算法——慕课作业——第一章 概论 + 第二章 线性表
  18. KingbaseES V8R6 集群运维系列 -- 命令行部署repmgr管理集群+switchover测试
  19. TeamViewer被发现用于(检测为)商业用途解决方案(绝对有效)
  20. 第1讲 几种密码技术的简要介绍——《图解密码技术》

热门文章

  1. 活动时的测试点及注意事项
  2. 网站推广中链接的作用
  3. 对于互联网广告投放,为何CPA受企业欢迎,CPM却占主流?
  4. break和continue语句的使用
  5. Android 手机蓝牙 (普通蓝牙篇)
  6. PoPo数据可视化第7期
  7. bootstrap设计进度条和圆点
  8. 汉字转拼音_gb2312 C#
  9. Qt的基础及基本代码说明
  10. swiper 上滑触发_【游戏攻略】如何清边—— 清边细节及常用清边策略(上)