Java教室: Garbage Collection 清除物件的顺序

原创 2001年03月29日 18:52:00

 ----------------------------------------------------------------
 
  (作者 : 艾群科技  萧松瀛) 
     
   Java 与 C 的其中一个差别就在於写 C 程式时,如果我们 new 了一个
 物件,同时我们也必须下  delete 来清除它, C 语言的核心并不会判断
 这个物件是否不再使用,而在程式执行时,需不需要将物件移除,也全都
 由使用者自行控制。其实这个原意很好,但是写到大型专案,或是 Multi
 -Thread 程式时,往往这些物件会变成难以控制,有时候我们甚至会试图
 去使用一个已经不存在的指标。  
     
   在 Java 中, JVM 帮我们管理这一层,因此当物件不在被使用时, JV
  M 会在"适当"的时间点将它由记忆体中移除。 
     
   所有的物件均继承 Object ,因此 Object 这个物件中,有一个很有用
 的 method 叫做 finalize() ,这一个 method 依照定义,当 Garbage C
 ollection 要将这个物件移除前会先呼叫这个物件的 finalize() 。也就
 是说,当我们在实作我们的 Class 的时候,最好将这一个 method overr
 ide 。这样一来,当 Garbage Collection 要清除物件的时候,就会执行
 到我们自己写的  finalize()。 
     
   因此我们设计了底下这个物件,这个物件在我们建立时,需要带入一个
  int 值,这一个 int 值,而当 finalize() 被执行的时候,他会将这个
  int 值列印出来,好让我们知道 Garbage Collection正准备清除哪一个
 物件。  
     
    public class testobject 
    { 
    private int itell; 
    public testobject() 
    { 
    this.itell = 0; 
    } 
    public testobject(int i) 
    { 
    this.itell = i; 
    } 
    public void finalize() 
    { 
    System.out.println("testobject id = "+itell); 
    } 
    } 
     
   接著,我写了底下这一个 testfinalize.java ,这一个 testfinalize
 .java 会宣告一个阵列,这一个阵列中,会存放 testobject 物件,届时
   我会将这一个阵列设为 null ,表示我不再使用这一个阵列了。 
     
    public class testfinalize 
    { 
    public static void main(String argv[]) 
    { 
    testobject [] testo = new testobject[2]; 
    testo[0] = new testobject(1); 
    testo[1] = new testobject(2); 
    testo = null; 
    System.out.println("finish..."); 
    } 
    } 
     
    执行的结果是 
     
    C:/temp/javajava testfinalize 
    finish... 
     
    C:/temp/java 
     
    奇怪,是 garbage collection 没有执行 finalize() 吗?? 不是的,
 是 garbage collection 根本没有被启动,在前面说过,garbage collec
 tion 会在适当的时机启动,而这一个 testfinalize 程式很小, JVM 认
 为不需要执行  Garbage Collection ,因此程式结束,记忆体释放。 
     
   是不是这样就没办法知道 garbage collection 做了时么事情??不是我
 们还可以透过两个 method 来建议 JVM 执行 garbage collection,一个
 是 System.gc(); ,另外一个建议的方式是 Runtime.getRuntime().gc()
 , System.gc() 也会执行 Runtime.getRuntime().gc() ,不论哪一个,
 他们都会建议  JVM 去执行另外一个 Thread ,这一个 Thread 会扫瞄所
 有没有被用到的物件,将他们清除,并且取得他们所占用的记忆体。因此
 我们将  testfinalize.java 加上一行如下 
     
    public class testfinalize 
    { 
    public static void main(String argv[]) 
    { 
    testobject [] testo = new testobject[2]; 
    testo[0] = new testobject(1); 
    testo[1] = new testobject(2); 
    testo = null; 
    System.gc(); 
    System.out.println("finish..."); 
    } 
    } 
     
    Compile  之後执行结果如下 
    C:/temp/javajava testfinalize 
    testobject id = 1 
    testobject id = 2 
    finish... 
     
    C:/temp/java 
     
   没错,我们看到了 testobject id = 1 以及 testobject id = 2 这两
 行了。  
     
   问题就这样解决了吗??非也!他事先清除阵列 testo[0] 接著再清除 t
  esto[1] 还是有其他的顺序?? 
     
    首先,我们先来看看 JLS 中对於 Garbage Collection 顺序的说明 
     
    12.6.2 Finalizer Invocations are Not Ordered 
     
   The Java programming language imposes no ordering on finalize
 method calls. Finalizers may be called in any order, or even con
 currently. As an example, if a circularly linked group of unfina
 lized objects becomes unreachable (or finalizer-reachable), then
  all the objects may become finalizable together. Eventually, th
 e finalizers for these objects may be invoked, in any order, or
 even concurrently using multiple threads. If the automatic stora
 ge manager later finds that the objects are unreachable, then th
  eir storage can be reclaimed.  
     
   It is straightforward to implement a class that will cause a s
 et of finalizer-like methods to be invoked in a specified order
 for a set of objects when all the objects become unreachable. De
  fining such a class is left as an exercise for the reader. 
     
    依照这个规格说明,我们发现, JVM 并没有依照一定的顺序来清除物
 件,然而实际上呢 ?? 
     
    我们再修改 testfinalize.java 让他成为底下的模式 
     
    public class testfinalize 
    { 
    public static void main(String argv[]) 
    { 
    testobject [] testo = new testobject[2]; 
    testo[1] = new testobject(2); 
    testo[0] = new testobject(1); 
    testo = null; 
    System.gc(); 
    System.out.println("finish..."); 
    } 
    } 
     
   也就是这一次,我们先产生 new testobject(2) 并且将他放到 testo[
  1] 然後再产生 new testobject(1),接著放到 testo[0] 。 
     
    执行结果如下  
    C:/temp/javajava testfinalize 
    testobject id = 2 
    testobject id = 1 
    finish... 
     
    C:/temp/java 
     
   没错,我们实际上执行这个程式的结果是先产生的物件, Garbage Col
  lection 先将他移除。 
     
   至於时么时候该使用 finalize() ? 通常仅需要记住一个原则,就是如
 果在产生物件的同时,我们有使用到一些资源,譬如 JDBC 连线,譬如开
 了个 socket 到另外一台机器,甚至开了个 TCP/IP Server等等,那么在
   finalize() 的时候,我们最好就需要尝试著将这些资源给释放。 
     
     
    执行环境 
    1. Sun Ultra 10 
    JDK 1.3.0 Hotspot Client 
    2. Windows 2000 
    JDK 1.3.0_01 Hotspot Client
 
 ----------------------------------------------------------------

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

也谈谈Java的垃圾收集(garbage collection)

垃圾收集是Java语言非常显著的特点,不像C语言那样,老是要考虑什么数字的越界什么的。什么是垃圾(garbage)呢?“An object is considered garbage when it ...
  • autofei
  • autofei
  • 2011年04月21日 12:48
  • 10856

Java中的垃圾回收是如何工作的?(How Garbage Collection works in Java)

注:此文是在blogspot(被墙)上看到的,能翻墙的同学们自己去看(点此此处), 顺道可以看看一些其他的资料;不能翻墙的同学在此将就将就。 我读过许多关于Java垃圾回收的文章,其中...
  • redhat456
  • redhat456
  • 2011年09月22日 21:27
  • 3781

关于JAVA中的Garbage Collection和finalize()

关于JAVA中的Garbage Collection和finalize() Java的内存释放涉及到Garbage Collection的概念,那么到底什么是Garbage Collection呢?中...
  • youhaodeyi
  • youhaodeyi
  • 2005年12月16日 13:37
  • 2920

Java的内存结构(Memory Structure)和垃圾收集(Garbage Collection)图解

JVM 内存包含如下几个部分: Heap Memory 存放Java对象 Non-Heap Memory 存放类加载信息和其它meta-dataOther 存放JVM 自身代码等 在J...
  • autofei
  • autofei
  • 2012年04月13日 02:48
  • 21480

[Understanding Java Garbage Collection]理解Java垃圾收集(二)

GC老年代老年代GC基本上是在空间慢的时候发生。执行过程与GC的类型有关,因此在你了解GC的种类之后更简单。根据JDK7,有5中GC类型。 Serial GC Parallel GC Parall...
  • xiangshimoni
  • xiangshimoni
  • 2015年03月25日 21:46
  • 1024

Understanding Java Garbage Collection

What are the benefits of knowing how garbage collection (GC) works in Java? Satisfying the intellect...
  • caoguanling2011
  • caoguanling2011
  • 2014年03月27日 20:33
  • 432

Tuning-java-garbage-collection-for-spark-applications

原文链接:https://databricks.com/blog/2015/05/28/tuning-java-garbage-collection-for-spark-applications.ht...
  • wl044090432
  • wl044090432
  • 2016年03月31日 15:08
  • 427

Java Garbage Collection

1. 垃圾回收的意义  在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。JVM...
  • DLUTBruceZhang
  • DLUTBruceZhang
  • 2013年06月03日 22:12
  • 2010

Python Garbage Collection 与 Objective-C ARC

转载请注明出处 http://www.jianshu.com/p/1cdfa6193854Python GC 与 Objective-C ARC提起GC(Garbage Collector)我们首先想...
  • u014205968
  • u014205968
  • 2017年04月06日 14:34
  • 2040

Garbage Collection | 节点复制算法

这次考察的是基于追踪的算法:节点复制算法。节点复制式收集器将整个堆等分成为两个半区(semi-space),一个包含现有的数据,另一个包含已被废弃的数据,节点复制式垃圾收集从filp两个半区的角色开始...
  • sweeterer
  • sweeterer
  • 2016年10月11日 14:46
  • 7327
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java教室: Garbage Collection 清除物件的顺序
举报原因:
原因补充:

(最多只允许输入30个字)