为什么最终没有被调用?

发布于 2024-12-10 05:37:13 字数 813 浏览 0 评论 0原文

我有几个关于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 如何解决循环引用?

I have couple of questions regarding garbage collector in java.

Q1.As far as I understand, finalize() gets called when object is out of scope and JVM is about to collect garbage. I thought finalize() method is called automatically by garbage collector, but it does not seems to work in this case. What is the explanation? Why is the need for me to explicitly call finalize() method?

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. Also, when is garbage collector invoked? I understand gc is a daemon thread and invoked by JVM depending on heap size remaining. Does that mean, JVM waits for the program to use threshold limit of resources and then notify the gc to sweep garbage objects.

EDIT: How does gc resolved circular references?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

天涯沦落人 2024-12-17 05:37:13

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

There is a lot to finalize() method which is frankly a lot to write, but in short:

An object is in the finalized state if it is still unreachable after its finalize method, if any, has been run. A finalized object is awaiting deallocation. Note that the VM implementation controls when the finalizer is run. You are almost always better off doing your own cleanup instead of relying on a finalizer. Using a finalizer can also leave behind critical resources that won't be recovered for an indeterminate amount of time.

In your case the reason it does not print is that you do not know when the finalizer thread will call the finalize() method. What is happening is that the program is terminating before anything can get printed. To check it:
edit the code inside main code by( NOTE: this does not guarrantee nor should you should ever rely on it but still it does prints some time)

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

There are a lot of disadvantages of using a finalize() right from taking more time in object construction to possibility of memory leakage and memory starvation. If you strongly refer to the same object inside the finalize() then it is never called the second time and thus can leave system in undesired state etc etc etc...
The only place where you should use finalize() is as a safety net to dispose any resources like InputStream uses it to close (which again there is no guarrantee that it will will br run when your program is still alive). Another place to use it is while using natives where garbage collector has no control.

For more info visit:

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

魄砕の薆 2024-12-17 05:37:13

q1) Finalize方法在对象被垃圾收集时被调用,因此,如果没有执行GC,您的终结器可能不会被调用。您只需调用 super 即可保留 Object 实现提供的行为。

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

q1) finalize method is called when the object is being garbage collected, thus, if no GC is being performed, your finalizer may not be called. You need to call super simply to preserve the behavior provided by Object implementation.

q2) the exact moment in which GC is performed depends on a lot of factors like: which JVM you are using, tuning parameters, amount of free heap, etc. So it does not only rely on a used heap threshold. You can also ask for a GC to be performed through System.gc() but you have no guarantee about if and when it will be actually executed.
You can find some details on how to configure GC in http://java.sun.com/performance/reference/whitepapers/tuning.html

演多会厌 2024-12-17 05:37:13

它最终会被调用,或者根本不会被调用,

基本上GC会扫描堆中所有无法访问的内容,并对这些内容运行终结器(之后它需要再次证明它是不可访问的,才能被释放) )

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

编辑:至于循环引用,它区分对象与最终确定方法和没有一个对象的对象

任何代码都可能无法访问该对象(这包括仍需要运行的终结器)

要被释放(从主内存中删除),当 2 个具有终结器的对象有资格让终结器运行 GC 任意选择时, 一个对象并在其上运行终结器,然后它可以运行另一个对象,

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

it gets called eventually or not at all

basically the GC scans the heap for everything that is not reachable and runs the finalizer on those (after which it needs to prove again it is not reachable for it to be freed)

however it can take a while (effectively undefined and actually dependent on program behavior) for the GC to find it which is why you shouldn't really rely on it to dispose of critical data

edit: as for circular references it distinguishes between objects with a finalize method and objects without one

for an object to be freed (deleted from main memory) it may not be reachable by any code (this includes finalizers that still need to run)

when 2 objects with finalizers are eligible to get the finalizers run the GC arbitrarily selects one object and runs the finalizer on it and then it can run the other object

note that a finalizer can run while the fields of the objects may or may not be finalized already

べ映画 2024-12-17 05:37:13

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();
    }
}

finalize() method is called automatically during garbage collection. System.gc() method forcibly calls garbage collector. but we will have to destroy object before.
example:

     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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文