为什么最终没有被召唤?

我有几个关于java中垃圾收集器的问题。

Q1。据我所知,当对象超出范围且JVM即将收集垃圾时,会调用finalize()。 我认为finalize()方法是由垃圾收集器自动调用的,但在这种情况下它似乎不起作用。 解释是什么? 为什么我需要显式调用finalize()方法?

public class MultipleConstruct { int x,y; public MultipleConstruct(int x) { this.x= x; y=5; System.out.println("ONE"); } @Override protected void finalize() throws Throwable { // TODO Auto-generated method stub super.finalize(); System.out.println("FINALIZED"); } public static void main(String[] args) throws Throwable { MultipleConstruct construct = new MultipleConstruct(3); } } 

Q2。 另外,什么时候调用垃圾收集器? 我理解gc是一个守护程序线程,由JVM根据剩余的堆大小调用。 这是否意味着,JVM等待程序使用资源的阈值限制,然后通知gc扫描垃圾对象。

编辑: gc如何解决循环引用?

finalize()方法有很多东西,坦率地写了很多,但简而言之:

如果一个对象在其finalize方法(如果有的话)运行后仍然无法访问,则它处于最终状态。 最终的对象正在等待释放。 请注意,VM实现控制何时运行终结器。 你几乎总是更好地做自己的清理,而不是依靠终结器。 使用终结器还可以留下在不确定的时间内无法恢复的关键资源。

在您的情况下,它不打印的原因是您不知道终结器线程何时将调用finalize()方法。 发生的事情是该程序在任何可以打印之前终止。 要检查它:编辑主代码中的代码(注意:这不是保证也不应该依赖它,但它仍会打印一段时间)

 for(int i =0;i<1000000;i++) { MultipleConstruct construct = new MultipleConstruct(3); construct = null; } 

使用finalize()有很多缺点,从在对象构造中花费更多时间到内存泄漏和内存不足的可能性。 如果你在finalize()中强烈引用相同的对象,那么它永远不会被第二次调用,从而可以使系统处于不希望的状态等等...你应该使用finalize()的唯一地方是作为安全网处理任何资源,如InputStream使用它来关闭(这也没有保证,当你的程序还活着时它会运行)。 使用它的另一个地方是使用垃圾收集器无法控制的本机。

欲了解更多信息,请访

http://jatinpuri.com/?p=106

q1)当对象被垃圾收集时调用finalize方法,因此,如果没有执行GC,则可能不会调用终结器。 您需要调用super来简单地保留Object实现提供的行为。

q2)执行GC的确切时刻取决于很多因素,例如:您正在使用的JVM,调整参数,可用堆的数量等等。因此,它不仅依赖于使用的堆阈值。 您也可以要求通过System.gc()执行GC,但您无法保证是否以及何时实际执行。 您可以在http://java.sun.com/performance/reference/whitepapers/tuning.html中找到有关如何配置GC的一些详细信息。

最终会被调用或根本不被调用

基本上GC扫描堆中的所有无法访问的内容并在那些上运行终结器(之后它需要再次certificate它是不可以被释放的)

然而,GC可能需要一段时间(实际上是未定义的并且实际上依赖于程序行为)才能找到它,这就是为什么你不应该真正依赖它来处理关键数据

编辑:对于循环引用,它区分具有finalize方法的对象和没有一个的对象

对于要释放的对象(从主内存中删除),任何代码都可能无法访问它(这包括仍然需要运行的终结器)

当具有终结器的2个对象有资格获得终结器运行时,GC任意选择一个对象并在其上运行终结器然后它可以运行另一个对象

请注意,终结器可以运行,而对象的字段可能已经或可能尚未完成

在垃圾收集期间自动调用finalize()方法。 System.gc()方法强制调用垃圾收集器。 但我们必须先破坏物体。 例:

  public class Sample { public Sample() { System.out.println("Object created"); } @Override public void finalize() { System.out.println("Object Destroyed"); } public static void main(String args[]) { Sample x=new Sample(); Sample y=new Sample(); x=null; y=null; System.gc(); } }