我应该在java中使用finalize()吗?

时间:2014-07-25 05:22:51

标签: java

为什么在Java中根本无法保证执行finalize()?是不应该使用finalize()方法???

考虑以下计划。

class Test{
   protected void finalize()
   {
       System.out.println("Will i execute?");
   }
   public static void main(String args[])
   {
         Test t=new Test();
   }
}

此程序运行时输出为空。我们知道finalize()用于在对象符合垃圾收集条件之前清除任何外部资源。 JVM将调用finalize()。在finalize()内,我们将指定在销毁对象之前必须执行的操作。 finalize()方法是邪恶的吗?

5 个答案:

答案 0 :(得分:3)

Javadoc link,因为会有很多引用。

  

我们知道finalize()用于在对象符合垃圾回收资格之前清除所有外部资源

没有。一旦对象符合垃圾收集条件,就可以调用finalize()。理论上finalize可以使对象不再符合垃圾收集条件,然后垃圾收集器会跳过它。如上所述

  

为对象调用finalize方法后,不再进一步   在Java虚拟机再次确定之前执行操作   没有任何方法可以访问此对象   任何尚未死亡的线程

     

为什么在Java中根本不保证执行finalize()?

保证运行。正如Javadoc所述

  

finalize的一般合同是,如果和何时调用它   Java™虚拟机已经确定不再有任何手段   任何尚未使用的线程都可以访问此对象   死亡,除非由于最终确定采取的行动   其他一些准备完成的对象或类。

什么不保证是何时或是否会发生垃圾收集。

  

我应该在java中使用finalize()吗?

这取决于您的使用案例。首先阅读javadoc并了解其含义。

答案 1 :(得分:2)

当垃圾收集确定没有对该对象的更多引用时,

finalize()由对象上的垃圾收集器调用。

您可以使用System.gc()显式调用垃圾回收并检查您的语句是否被打印。  但是JVM可以忽略您的请求(实际上取决于JVM的实现......)。只有当JVM的内部状态告诉它有太多垃圾并且需要收集时,它才会运行GC(并且将执行行)将被打印。

答案 2 :(得分:1)

如果我理解了您的问题,您可以使用System.gc()来请求垃圾收集,

@Override
protected void finalize() {
  System.out.println("I will execute.");
}

public static void main(String args[]) {
  Test t = new Test();
  t = null;                     // <-- make it eligible for gc.
  System.gc();                  // <-- request gc.
  System.runFinalization();     // <-- run finalization(s).
  System.out.println("Exit");   // <-- exit.
}

如果您注释掉System.runFinalization(); -

,您可能会找到输出交换的顺序,具体取决于您的JVM
public static void main(String args[]) {
  Test t = new Test();
  t = null;                     // <-- make it eligible for gc.
  System.gc();                  // <-- request gc.
  // System.runFinalization();  // <-- run finalization(s).
  System.out.println("Exit");   // <-- exit.
}

答案 3 :(得分:0)

从内存中删除对象之前垃圾收集线程调用该对象的finalize()方法,并提供执行任何类型清理操作的机会。

通常,在以下情况下,对象有资格在Java中进行垃圾收集:

  1. 该对象的所有引用都明确设置为null,例如object = null。
  2. 在块内创建对象,并且一旦控制退出该块,引用就会超出范围。
  3. 父对象设置为null,如果对象保存另一个对象的引用,并且当您设置容器对象的引用null时,子对象或包含对象将自动符合垃圾回收的条件。
  4. 如果一个对象只有WeakHashMap的实时引用,它就有资格进行垃圾回收。

    public Test(){ System.out.println("Object created"); } protected void finalize(){ System.out.println("Will i execute?"); } public static void main(String args[]){ Test test = new Test(); test = null; new Test(); System.gc(); }

答案 4 :(得分:0)

在将该类的对象收集为垃圾之前,jvm调用任何特定类的

finalize()。

现在接下来的问题是当一个类的对象被收集为垃圾? 答案是:

当没有更多对象引用该对象时,或者根本没有对象引用指向该分配的内存空间或者对象只有通过WeakHashMap进行实时引用时,它将有资格进行垃圾回收。 Read more here

作为一个选项,我们可以使用System.gc()或Runtime.gc()来请求jvm来考虑垃圾收集。但是jvm是否会听取或忽略您的请求,这取决于以下因素:

  1. JVM&amp; amp;的内部实施垃圾收集算法
  2. Java堆大小
  3. Heap中提供的可用内存