`
yzmduncan
  • 浏览: 327032 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

java垃圾回收机制——虚拟机和finalize

阅读更多

java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize()

  (1).对象不一定会被回收。

  (2).垃圾回收不是析构函数。

  (3).垃圾回收只与内存有关。

  (4).垃圾回收和finalize()都是靠不住的,只要JVM还没有快到耗尽内存的地步,它是不会浪费时间进行垃圾回收的。

  有时当撤消一个对象时,需要完成一些操作。例如,如果一个对象正在处理的是非Java 资源,如文件句柄或window 字符字体,这时你要确认在一个对象被撤消以前要保证这些资源被释放。为处理这样的状况,Java 提供了被称为收尾(finalization )的机制。使用该机制你可以定义一些特殊的操作,这些操作在一个对象将要被垃圾回收程序释放时执行。

  要给一个类增加收尾(finalizer ),你只要定义finalize ( ) 方法即可。Java 回收该类的一个对象时,就会调用这个方法。在finalize ( )方法中,你要指定在一个对象被撤消前必须执行的操作。垃圾回收周期性地运行,检查对象不再被运行状态引用或间接地通过对象引用。就在对象被释放之前,Java 运行系统调用该对象的finalize( ) 方法。其他

  finalize()方法的通用格式如下:

  protected void finalize( )

  {

  // finalization code here

  }

  其中,关键字protected是防止在该类之外定义的代码访问finalize()标识符。该标识符和其他标识符将在第7章中解释。

  理解finalize( ) 正好在垃圾回收以前被调用非常重要。例如当一个对象超出了它的作用域时,finalize( ) 并不被调用。这意味着你不可能知道何时——甚至是否——finalize( ) 被调用。因此,你的程序应该提供其他的方法来释放由对象使用的系统资源,而不能依靠finalize( ) 来完成程序的正常操作。

  注意:如果你熟悉C ,那你知道C 允许你为一个类定义一个撤消函数(destructor ),它在对象正好出作用域之前被调用。Java不支持这个想法也不提供撤消函数。finalize() 方法只和撤消函数的功能接近。当你对Java 有丰富经验时,你将看到因为Java使用垃圾回收子系统,几乎没有必要使用撤消函数。

  理解finalize()-析构函数的替代者

  by Tim Gooch

  在许多方面,Java 类似于 C++Java 的语法非常类似于 C++Java 有类、方法和数据成员;Java 的类有构造函数; Java 有异常处理。

  但是,如果你使用过 C++ 会发现 Java 也丢掉一些可能是你熟悉的特性。这些特性之一就是析构函数。取代使用析构函数,Java 支持finalize() 方法。

  在本文中,我们将描述 finalize() C++ 析构函数的区别。另外,我们将创建一个简单的 Applet 来演示 finalize() 是如何的。工作

  最终的界限

  与 Java 不同,C++ 支持局部对象(基于栈)和全局对象(基于堆)。因为这一双重支持,C++ 也提供了自动构造和析构,这导致了对构造函数和析构函数的调用,(对于堆对象)就是内存的分配和释放。

  在 Java 中,所有对象都驻留在堆内存,因此局部对象就不存在。结果,Java 的设计者觉得不需要析构函数(象 C++ 中所实现的)。

  取而代之,Java 定义了一个特殊的方法叫做finalize() ,它提供了 C++ 析构函数的一些功能。但是,finalize() 并不完全与 C++ 的析构函数一样,并可以假设它会导致一系列的问题。finalize() 方法作用的一个关键元素是 Java 的垃圾回收器。

  垃圾回收器

  在 C/C++Pascal和其他几种多种用途的编程语言中,开发者有责任在内存管理上发挥积极的作用。例如,如果你为一个对象或数据结构分配了内存,那么当你不再使用它时必须释放掉该内存。

  在 Java 中,当你创建一个对象时,Java 虚拟机(JVM)为该对象分配内存、调用构造函数并开始跟踪你使用的对象。当你停止使用一个对象(就是说,当没有对该对象有效的引用时),JVM 通过垃圾回收器将该对象标记为释放状态。

  当垃圾回收器将要释放一个对象的内存时,它调用该对象的finalize() 方法(如果该对象定义了此方法)。垃圾回收器以独立的低优先级的方式运行,只有当其他线程挂起等待该内存释放的情况出现时,它才开始运行释放对象的内存。(事实上,你可以调用System.gc() 方法强制垃圾回收器来释放这些对象的内存。)

  在以上的描述中,有一些重要的事情需要注意。首先,只有当垃圾回收器释放该对象的内存时,才会执行finalize()。如果在 Applet 或应用程序退出之前垃圾回收器没有释放内存,垃圾回收器将不会调用finalize()

  其次,除非垃圾回收器认为你的 Applet 或应用程序需要额外的内存,否则它不会试图释放不再使用的对象的内存。换句话说,这是完全可能的:一个 Applet 给少量的对象分配内存,没有造成严重的内存需求,于是垃圾回收器没有释放这些对象的内存就退出了。

  显然,如果你为某个对象定义了finalize() 方法,JVM 可能不会调用它,因为垃圾回收器不曾释放过那些对象的内存。调用System.gc() 也不会起作用,因为它仅仅是给 JVM 一个建议而不是命令。

  finalize() 有什么优点呢?

  如果finalize() 不是析构函数,JVM 不一定会调用它,你可能会疑惑它是否在任何情况下都有好处。事实上,在 Java 1.0 中它并没有太多的优点。

  根据 Java 文档,finalize() 是一个用于释放非 Java 资源的方法。但是,JVM 有很大的可能不调用对象的finalize() 方法,因此很难证明使用该方法释放资源是有效的。

  Java 1.1 通过提供一个System.runFinalizersOnExit() 方法部分地解决了这个问题。(不要将这个方法与 Java 1.0 中的System.runFinalizations() 方法相混淆。)不象System.gc() 方法那样,System.runFinalizersOnExit() 方法并不立即试图启动垃圾回收器。而是当应用程序或 Applet 退出时,它调用每个对象的finalize() 方法。

  正如你可能猜测的那样,通过调用System.runFinalizersOnExit() 方法强制垃圾回收器清除所有独立对象的内存,当清除代码执行时可能会引起明显的延迟。

  继承finalize()?

  顺便,如果你在类中定义了finalize() ,它将不会自动调用基类中的方法。在我们讨论了finalize() C++ 的析构函数的不同点后,对这个结论不会惊讶,因为为某个类定制的清除代码另一个类不一定会需要。

  如果你决定要通过派生一个类的finalize() 方法来调用基类中的finalize() 方法,你可以象其他继承方法一样处理。

  protected void finalize()

  {

  super.finalize();

  // other finalization code...

  }

  除了允许你控制是否执行清除操作外,这个技术还使你可以控制当前类的finalize() 方法何时执行。

  结论

  然而有益的是,Java 的自动垃圾回收器不会失去平衡。作为便利的代价,你不得不放弃对系统资源释放的控制。不象 C++ 中的析构函数,Java Applet 不会自动执行你的类中的finalize() 方法。事实上,如果你正在使用 Java 1.0,即使你试图强制它调用finalize() 方法,也不能确保将调用它。

  因此,你不应当依靠finalize() 来执行你的 Applet 和应用程序的资源清除工作。取而代之,你应当明确的清除那些资源或创建一个try...finally 块(或类似的机制)来实现。

 

 

 

分享到:
评论
1 楼 seawh411 2012-02-24  
  不错有见地....

相关推荐

    Java垃圾回收机制的finalize方法实例分析

    主要介绍了Java垃圾回收机制的finalize方法,结合实例形式分析了finalize方法的特点及在垃圾回收机制中的相关操作技巧,需要的朋友可以参考下

    简单理解Java的垃圾回收机制与finalize方法的作用

    主要介绍了简单理解Java的垃圾回收机制与finalize方法的作用,着重讲解了Java的GC销毁对象的过程,需要的朋友可以参考下

    浅谈关于C#的垃圾回收机制

    理解C#垃圾回收机制我们首先说一下CLR(公共语言运行时,Common Language Runtime)它和Java虚拟机一样是一个运行时环境,核心功能包括:内存管理、程序集加载、安全性、异步处理和线程同步。 CTS(Common Type ...

    Java垃圾回收finalize()作用详解

    Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作,这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。

    垃圾回收finalize的用处(算法 演示)

    对于一个JAVA程序员来说内存就是生命,如果出现内存泄露,或者内存不能释放,那程序就危险了,虽然JAVA有垃圾回收,但是你如果真的理解垃圾回收的原理,就应该看看这个!

    Java中finalize()的用法

    配方详细介绍了在Java中finalize()的用法。

    Java9垃圾回收方法finalize() 原理解析

    主要介绍了Java9垃圾回收方法finalize() 原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    《剑指offer》Java深入理解final、finally、finalize.pdf

    finalize 是一个不让人待见的方法,它是对象祖宗 Object 中的一个方法,finalize 机制现在已经不推荐使用了。本篇文章,cxuan 就带你从这三个关键字入手,带你从用法、应用、原理的角度带你深入浅出理解这三个...

    java 基础之final、finally和finalize的区别

    主要介绍了java 基础之final、finally和finalize的区别的相关资料,需要的朋友可以参考下

    java.lang.object源码-finalize-:个人博客(http://bit.ly/javafinalize)上java.lang

    java.lang.object原始码最终不推荐使用java.lang.Object.finalize() 我的博客文章中的示例的Gradle源代码存储库。 在Linux Mint(SUSE Linux)上构建和测试。 由于gradle当前不支持Java 11,因此可以使用标准Java...

    Java中final,finally,finalize三个关键字的区别_动力节点Java学院整理

    Java中final,finally,finalize三个关键字的区别_动力节点Java学院整理

    JAVA面试题解惑系列合集

    1.4 JAVA面试题解惑系列(四)——final、finally和finalize的区别 1.5 JAVA面试题解惑系列(五)——传了值还是传了引用? 1.6 JAVA面试题解惑系列(六)——字符串(String)杂谈 1.7 JAVA面试题解惑系列(七)...

    关于Java的几个经典问题

    到底创建了几个String对象(三)——变量(属性)的覆盖 (四)——final、finally和finalize的区别 (五)——传了值还是传了引用(六)——字符串(String)杂谈 (七)——日期和时间的处理 (八)——聊聊基本...

    Java面试题及答案-java面试题

    Java 中的 final、finally 和 finalize 关键字有什么区别? final:当用“final”关键字声明一个变量时,它的值一旦被赋值就不能改变。当使用“final”关键字声明方法时,它不能在子类中被覆盖。当用“final”...

    超硬核!!!一篇文章搞定整个JVM的垃圾回收系统

    JVM的垃圾回收机制JVM的垃圾回收机制1 什么是垃圾回收机制2 finalize方法作用3 新生代、老年代、永久代(方法区)的区别3.1 为什么要这样分代:3.2 Minor GC、Major GC、Full GC区别及触发条件4 如何判断对象是否存活...

    .Net 垃圾回收机制详细介绍

    .NET垃圾回收器会保证: l 每个对象都会被摧毁,它的析构函数一定会被运行。当一个程序结束后,所有对象都会被销毁。 l 每个对象只被销毁一次。 l 每个对象只有在不可抵达时(即不存在到该对象

    java大厂面经、直击BAT

    ## 二.finally finally 一定会被执行,如果 finally ...finalize()方法是Object类的一个protected方法,它是在对象被垃圾回收之前由Java虚拟机来调用的。 ## 四. finally到底是在return之前执行还是return之后执行?

    大厂真题之京东-Java实习生

    1、哪些情况下的对象会被垃圾回收机制处理掉? 利用可达性分析算法,虚拟机会将一些对象定义为 GC Roots,从 GC Roots 出发沿着引用链 向下寻找,如果某个对象不能通过 GC Roots 寻找到,虚拟机就认为该对象可以被...

    Java中针对finalize的实现和相应的执行过程

     此类是一个package类型,表示它并不是公开的一部分,继承自Reference, 即表示也是一种特定的引用类型,因此每个包装在其中的对象在被回收之前,自己都会放到指定的referqyebceQueue当中.  这个引用对象专门为...

    java面试题 谈谈final, finally, finalize的区别

    一,谈谈final, finally, finalize的区别。 java面试题

Global site tag (gtag.js) - Google Analytics