2014-03-13 57 views
1

我有以下有關finalize()方法和垃圾回收Java的問題。是否有強制執行finalize()方法的方法

  1. 有沒有一種方法可以強制finalize()方法?
    以下方法對JDK棄用的原因是什麼?

    Runtime.runFinalizersOnExit(true);

  2. 除了上面的問題,我正在閱讀文章http://javarevisited.blogspot.com/2011/04/garbage-collection-in-java.html。在此,請參閱作者說在調用垃圾收集器之前調用finalize()的第5點。那麼這件事情是否確實發生?我的意思是在執行垃圾收集器方法之前總是調用finalize()方法?

  3. 假設我堆裏有很多垃圾,但垃圾收集器沒有執行。那麼這不是一個糟糕的行爲或JVM的缺陷嗎?

  4. 它是如何降低我的應用程序的性能,因爲垃圾收集沒有發生?

+0

object.finalize(); 您可以通過強制finalize()爲要銷燬的對象的實例運行來銷燬該對象。 –

回答

0

finalize方法may never actually get called,使絕對需要運行任何關鍵清理代碼應該去別的地方。你應該自己管理它 - 當你完成一個持有某些資源的對象時,明確地進行清理(例如實現一個close方法)。

0

你根本不應該使用finalize出於這樣的原因。 除了給出的答案,我給你一些示例代碼。它證明,作爲一名程序員,你通常不能確定最終確定會運行。示例1和5不相關,因爲它們很少有關係。但是3,4和5有時會這樣。

並請閱讀約PhantomReference s。沒有提及PhantomReference s,關於最終確定的任何問題的答案都不完整。您可以在非守護線程中處理這些線程,並確保在處理所有JVM之前不會退出。

package com.example.foo; 

import java.io.ByteArrayOutputStream; 
import java.io.OutputStream; 
import java.util.LinkedList; 
import java.util.List; 

/** 
* Demonstration of failing finalize-implementations. Just run main, wait and see that it does not 
* actually print any messages other than "good bye!", even though there are 5 
* <code>System.out.println(...)</code> in the finalize-methods. 
* 
* <p> 
* However, finalize is run even if the instance was not created properly (Exception in 
* constructor). This may lead to problems, as the resources to close might not even exist. 
* 
* <p> 
* This answers this question: "Why is there no guarantee that {@link Object#finalize()} is run?" 
* 
* <p> 
* If you want an answer to the question: "Then what can I do to properly use finalize()?" <br/> 
* The answer is: Don't! <br/> 
* Not just because of the problems presented here. There are actually more problems! <br/> 
* Here's a better alternative: http://claude-martin.ch/java-cleanup/ 
*/ 
public class SomeClass { 

    /** 
    * Finalize of Object is not invoked by some JVMs because it is known to be empty. This is 
    * relevant if you thought you could use a tools that can intercept invocation of finalize (as in 
    * aspect-oriented programming). 
    */ 
    static final class Finalize1 { 
    // no finalize 
    } 

    /** Class and method not final. */ 
    static class Finalize2 { 
    @Override 
    protected void finalize() throws Throwable { 
     // not final -> extending class doesn't have to call this method. 
     System.out.println("Finalize2"); 
    } 
    } 

    /** 
    * Finalize allocates new data and fails. GC runs it but you have no guarantee that the JVM can 
    * run it successfully. 
    */ 
    static final class Finalize3 { 
    @Override 
    protected void finalize() throws Throwable, OutOfMemoryError { 
     // What if memory is already running out? 
     // Chances are high - why else would gc be running? 
     // Then even a small array could fail: 
     byte[] bytes = new byte[Integer.MAX_VALUE]; 
     // OutOfMemoryError was thrown! 
     System.out.println("Finalize3 " + bytes[0]); 
     // Also not run: 
     super.finalize(); 
    } 
    } 

    static Finalize4 finalize4; 

    /** 
    * This is just to show that you, as the author of a class, can not prevent that an instance is 
    * referenced from a static field. This is also true for all data structures that exist until the 
    * JVM exits. 
    */ 
    static final class Finalize4 { 
    @Override 
    protected void finalize() throws Throwable { 
     System.out.println("Finalize4"); 
    } 
    } 

    /** 
    * JVM could end abruptly. Again, you have no control over this when you write a class. 
    */ 
    static final class Finalize5 { 
    @Override 
    protected void finalize() throws Throwable { 
     System.out.println("Finalize5"); 
    } 
    } 

    /** Runs Garbage Collection. */ 
    static void gc(int n) { 
    final List<byte[]> list = new LinkedList<>(); 
    try { 
     while (true) 
     list.add(new byte[1024 * 1024]); 
    } catch (OutOfMemoryError e) { 
     // Now GC is needed... 
    } 
    for (int i = 0; i < n; i++) { 
     System.gc(); 
     try { // Give it time: 
     Thread.sleep(100); 
     } catch (InterruptedException e) { 
     } 
    } 
    } 

    public static void main(String[] args) { 
    gc(0); // fills memory 

    // 1) no finalize implemented: 
    new Finalize1(); 

    // 2) no call to super.finalize(): 
    new Finalize2() { 
     private OutputStream resource = new ByteArrayOutputStream(); 

     @Override 
     protected void finalize() throws Throwable { 
     // Not calling super.finalize() ! 
     this.resource.close(); 
     } 
    }; 

    // 3) Failing finalize: 
    new Finalize3(); 

    // 4) static reference: 
    finalize4 = new Finalize4(); 

    // Now let's try to get rid of them: 
    gc(20); 

    // 5) No time: 
    new Finalize5(); 
    System.out.println("good bye!"); 
    System.exit(0); 
    } 

}