`
yzmduncan
  • 浏览: 330415 次
  • 性别: 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入门--简述Java语言回收机制

    ### Java入门——深入理解Java语言回收机制 #### 一、垃圾回收(Garbage Collection)概述 在编程领域,特别是对于初学者来说,了解并掌握Java的垃圾回收机制是非常重要的。与C++等需要手动管理内存的语言不同,...

    计算机编程JAVA面试题集.doc

    常见的垃圾回收机制包括分代复制、标记垃圾回收和增量垃圾回收。垃圾回收器会在不可预知的时间回收不再使用的对象。 4. **线程同步**:Java提供了多种线程同步机制,如`synchronized`关键字、`wait()`、`notify()`...

    JVM垃圾回收与调优详解(1)1

    Java 虚拟机(JVM)的内存管理和垃圾回收是优化Java应用程序性能的关键环节。本文将详细探讨JVM中的垃圾回收与调优,重点包括内存分配策略、对象的生命周期以及垃圾回收的判断标准。 首先,JVM内存分为新生代...

    java嵌入式开发讲座(第一讲)

    - **垃圾回收机制**:CLDC的垃圾回收机制更加简单,不支持finalize方法。 - **浮点数支持**:默认情况下,CLDC不支持浮点数运算,这是因为许多低端设备不具备浮点运算能力。 - **CDC (Connected Device ...

    java笔试面试题目,很多很全

    5. **内存管理**:垃圾回收机制(GC)的基本原理,理解堆内存和栈内存的区别,以及 finalize() 方法的作用。 6. **多线程**:线程的创建(Thread类和Runnable接口)、同步机制(synchronized关键字、Lock接口及其...

    java和Javaweb_面试题大全

    垃圾回收机制 - **优点**: - 自动管理内存,减少程序员手动管理内存的工作量。 - 防止内存泄漏,提高内存使用的效率。 - 提高程序的健壮性和安全性。 - **原理**: - 垃圾回收器自动检测程序中不再使用的...

    jvm内存管理,pdf

    通过以上内容可以看出,深入理解JVM内存管理和垃圾收集机制对于提高应用程序的性能至关重要。尽管现代JVM已经非常智能,能够自动管理大部分内存相关的工作,但在面对复杂的应用场景时,仍然需要开发人员具备一定的...

    JAVA语言及WWW技术复习题.doc

    20. **垃圾回收**:当一个对象被视为垃圾时,其`finalize()`方法会被自动调用,但在实际编程中不推荐依赖此机制进行资源清理。 21. **Java可执行文件**:Java虚拟机(JVM)运行的是`.class`文件。 22. **变量定义*...

    java牛人总结

    `final`关键字用于声明不可变的变量或方法,`finally`块用于确保代码段在异常发生或正常执行后总能执行,`finalize`方法是`Object`类的一个方法,用于垃圾回收前的资源清理,但不应被直接调用,而应由JVM自动调用。...

Global site tag (gtag.js) - Google Analytics