0

As I know, there's no guarantee that Object.finalize() is called always. but If there an important non-GC resource, and user didn't call close() accidentally, How can I free the resource?

PS. Does Object.Finalize() in .NET have the same problem? If so, how can I solve this problem in that case?

ikh
  • 10,119
  • 1
  • 31
  • 70

3 Answers3

2

You should use try-finally or better try-with-resources

try(Resource res = /*aquire resource*/){
//do stuff
}catch(Exception e //or watever){
//handle exceptions
}

and how to do it before Java7 :

Resource res = null;
try{
res = //aquire resource
    //do stuff 
}catch(Exception e /*or whatever*/){
 //handle exceptions
}finally{
    if(null != res){
        res.close();
    }
}

In .Net you should use

using (Resource resource = /*aquire resource*/)
{
    //do stuff
}

The simple answer is that YOU CANNOT. Such behavior is a BUG and you should locate it and fix it.

Svetlin Zarev
  • 14,713
  • 4
  • 53
  • 82
1

.Net have the same problem, Finalize method is not reliable. So in .Net 2.0 to address this problem Safe Handles are introduced, which provides a reliable way to release the unmanaged resource.

All you have to do is inherit your class from SafeHandle or CriticalHandle. These both indeed derives from CritialFinializationObject which turns to be the key for reliablity.

Read more about safehandles here.

P.S:This is only partial answer, am a .Net guy so apologizes for no java part of answer.

Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
  • I've just read about safe handles from your link and they seem to address issues which don't even exist in Java, while still being as weak a mechanism as Java finalizers. – Marko Topolnik Jan 19 '14 at 11:48
  • @MarkoTopolnik Am not sure about which issues you think doesn't even exist in java? – Sriram Sakthivel Jan 19 '14 at 12:12
  • Accessing a resource over a handle which has already been invalidated, and then reused for another resource. `SafeHandle` is about preventing the usage of a *freed* resource handle as if it was still taken. – Marko Topolnik Jan 19 '14 at 12:23
  • @MarkoTopolnik `SafeHandle` is not only about preventing the usage of a freed resource handle as if it was still taken. Its main goal is to release the resource which was not cleaned up properly in time. – Sriram Sakthivel Jan 19 '14 at 13:42
  • Are there any timeliness guarantees for it? As in, "the resource is guaranteed to be freed within 10 ms of its handle becoming unreachable"? If not, then it's in the same class of reliability as Java's finalizers. – Marko Topolnik Jan 19 '14 at 13:46
  • @MarkoTopolnik No timely guarantee; but it is the part of garbage collection. you can't expect finalizers to be called for sure, but you can expect safe handle's `Finalize` will be called for sure **before the object's memory is reclaimed** – Sriram Sakthivel Jan 19 '14 at 14:57
  • Yes, that's what I have in mind: Java doesn't need SafeHandles for that. However the inadequacy of the finalization mechanism is the premise of this question and OP is asking how to improve on it. – Marko Topolnik Jan 19 '14 at 15:36
  • Um, The msdn says "The finalizer for any types deriving from CriticalFinalizerObject is given the opportunity to execute and will not be aborted, assuming the finalizer correctly follows the rules for a constrained execution region (CER).". Must I study how to write CER code to use this solution? T.T – ikh Jan 20 '14 at 01:42
  • Here are the guidelines to write [CER code](http://msdn.microsoft.com/en-us/library/ms228973%28v=vs.110%29.aspx) – Sriram Sakthivel Jan 20 '14 at 06:42
0

finalize has the same problem in .NET (i.e. if the object is never garbage collected, then finalize will never be called)

In Java, the best practice to guarantee cleanup is:

final Resource resource = getResource();
try {
    // Do stuff
    ...
} finally {
    resource.dispose();
}

In .NET, the best practice to guarantee cleanup is:

using (Resource resource = GetResource())
{
    // Do stuff
    ...
}
Jack
  • 1,064
  • 8
  • 11
  • 1
    This also doesn't answers the question – Sriram Sakthivel Jan 19 '14 at 09:52
  • doesn't answer it , because there is no answer to this question! It's the programmer's responsibility to take care of the resources, and when the program has a memory leak it's again the programmers responsibility to find it and fix it. If he doesn't use the mechanisms for resource management provided in the language it.s again his problem. He should find those pieces of code and fix them accordingly!!! – Svetlin Zarev Jan 19 '14 at 10:21
  • @SvetlinZarev **Why no answer?** there is an answer, atleast for .net. refer my answer for details! – Sriram Sakthivel Jan 19 '14 at 10:28
  • Well, I'm not much into .Net so I cannot comment on your answer, but either way it does not work for java. And this is more like a workaround for the `real` problem, rather than a fix. Also it does not work for third party code, which may leak resources internally. So strictly speaking it doesn't answer the question :) – Svetlin Zarev Jan 19 '14 at 10:37