当我们在其上显式调用finalize()时,是否释放了对象内存? [英] Is Object memory freed when we explicitly call finalize() on it?

查看:123
本文介绍了当我们在其上显式调用finalize()时,是否释放了对象内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就我的理解最终确定()和GC是两个不同的方面。 GC使用finalize()方法释放对象内存。我们不能说明GC何时会发生(即使我们明确地调用了System.gc())。但是我们可以在一个Object上明确地调用finalize()。

 函数会立即执行(内存释放)还是等待GC 
像System.gc()调用一样发生?

同样根据文档,finalize方法永远不会由Java虚拟机多次调用给出的对象。



那么当我们先调用finalize()并且在稍后的时间发生GC时会发生什么。

 如果在显式调用object.finalize()时没有释放对象内存,那么将不会被
调用再次在GC过程中违反只调用一次规则?


解决方案

你完全错了。

简短回答:
finalize()是一种清理资源的方法(如打开的文件)就在对象准备好垃圾收集之前(当没有对象强引用它时)。它可能不会被调用。这是一个超前的内存释放。



长答案:

有一个单独的守护进程线程称为finalizer线程负责调用finalize()方法。定位队列是准备好调用finalize()方法的对象的队列。


  1. 创建对象时,JVM会检查如果用户已经重写了finalize()方法。如果它有,那么它在内部注意到这个特定的对象有finalize()方法。

当一个对象准备好进行垃圾收集时,垃圾收集器线程会检查这个特定对象是否具有(1)。


  • 2a)如果没有,则发送垃圾回收。



    2b)它已经存在,然后它被添加到最终化队列中。它从表(1)中删除对象的入口。




终结者线程继续轮询队列。对于队列中的每个对象,都会调用它的finalize()方法。从(2)中调用finalize()循环后再次重复。如果这个对象仍然没有强大的参考,然后发送给GC。如果
它已经然后ALWAYS(2a)被调用,因为该条目在(2b)中被删除

 基本上finalize )方法只被调用一次。 

那么上述周期的问题是什么?


从(1)开始。它需要额外的时间来创建对象。 Java中的内存分配速度比malloc / calloc快5到10倍。所有获得的时间都在表中记录对象的过程中丢失了。我曾尝试过。在一个循环中创建100000个对象,并测量程序在两种情况下终止所用的时间:一个没有finalize(),另一个没有finalize()。发现它速度提高了20%。(b)从内存泄漏和饥饿中获得(b):b
$ b

如果队列中的对象引用了大量内存资源,那么除非该对象已准备好用于GC,否则所有这些对象都不会被释放。如果所有对象都是重量级对象,则可能会出现短缺。



从(2b)开始:因为finalize()只被调用一次,如果在finalize()中有一个很强的this对象引用。下一次,该对象的finalie()永远不会被调用,因此可以使对象处于不一致的状态。



如果在finalize()内引发异常,它将被忽略。 / b>

您不知道何时调用finalize(),因为您无法控制何时调用GC。有时可能发生的是,您正在finalize()中打印值,但输出从不显示,因为您的程序可能在调用finalize()时终止。



<因此请避免使用它。相反,创建一个方法say dispose(),它将关闭必需的资源或最终的日志等。


As far as my understanding goes finalize() and GC are two different aspects. GC uses finalize() method to free Object memory. We cannot state when GC will occur(even if we explicitly call System.gc()). But we can explicitly call finalize() on an Object.

Will the function be executed immediately(memory freed) or it waits till GC
occurs like System.gc() call?

Also as per the docs the finalize method is never invoked more than once by a Java virtual machine for any given object.

So what happens when we call finalize() first and GC happens at a later point of time.

If object memory is not freed on explicit call to object.finalize() then would't 
it being called again in the GC process violate the calling only once rule? 

解决方案

You have got it completely wrong.

Short answer: finalize() is a means to clean up resources (such as open files) just before the object is ready for garbage collection ( when no object has strong reference to it). It might/not be called. It is one step ahead of memory deallocation.

Long answer:

There is a separate daemon thread called as finalizer thread which is responsible for calling finalize() method . Finalization queue is the queue where objects which are ready to be called finalize() method are placed.

  1. When an Object is created, JVM checks if the user has overridden the finalize() method. If it has then it internally notes that this particular object has finalize() method.

When an object is ready for garbage collection, then the garbage collector thread checks if this particular object has finalize() from table mentioned in (1).

  • 2a) If it doesn’t then it is sent for garbage collection.

    2b) It is has, then it is added to the finalization queue. And it removes the entry of the object from the table (1).

Finalizer thread keeps polling the queue. For every object in the queue, its finalize() method is called. After calling the finalize() cycle from (2) is again repeated. If this object still has no strong reference, then sent for GC. If it has then ALWAYS (2a) is called because the entry was deleted in (2b)

Basically finalize() method is only called once.

So what’s the issue with the above cycle?

From (1). Its take extra time in object creation. Memory allocation in Java is 5x to 10x faster than malloc/calloc etc. All the time gained is lost in the procedure of noting the object in the table etc. I once tried it. Create 100000 objects in a loop and measure the time taken for program to terminate in 2 cases: One with no finalize(), Second with finalize(). Found it to be 20% faster.

From (2b): Memory Leakage and Starvation. If the object in the queue has references to a lot of memory resources, then all those objects wont get freed unless this object is ready for GC.If all the objects are heavy weight objects, then there can be a shortage.

From (2b): Because finalize() is called only once, what if in teh finalize() you had a strong reference to "this" object. Next time the object’s finalie() is never called hence can leave the object in an inconsistent state.

If inside finalize() an exception is thrown, it is ignored.

You do not know when finalize() is called as you have no control over when GC is called. Sometimes it might happen that you are printing the value’s in finalize() but the output is never shown, because your program might have got terminated by the time finalize() is called.

Hence avoid using it. Instead create a method say dispose() which will close the necessory resources or for final log etc.

这篇关于当我们在其上显式调用finalize()时,是否释放了对象内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆