Destructor in java?

J

John Smith

I am making a wrapper around an existing C library through JNI. I have two
functions Init() and Free() which allocates and deallocates resources.

How can I have the wrapper class call Free() when it runs out of scope?

The alternative is ofcourse to let users of the wrapper class call the Free
function specificly.

-- John
 
G

Gordon Beaton

I am making a wrapper around an existing C library through JNI. I
have two functions Init() and Free() which allocates and deallocates
resources.

How can I have the wrapper class call Free() when it runs out of
scope?

The alternative is ofcourse to let users of the wrapper class call
the Free function specificly.

You will have to call Free() explicitely. You can do that from a
finalizer, but IMO it's better to have an explicit dispose() method
that users of your class should call.

/gordon
 
I

Ingo R. Homann

Hi,

Gordon said:
You will have to call Free() explicitely. You can do that from a
finalizer, but IMO it's better to have an explicit dispose() method
that users of your class should call.

Although this is 100% correct, in practise the finalize-mechanism works
*much* better than it should do theoretically.

So, perhaps it is a good idea to go both ways: Explain the "users" that
they have to call it and call it in the finalizer as well. (Of course
you must ensure that there are no problems when dispose() is called twice.)

Note that there are also mechanisms like shutdownHook() and the
java.lang.ref-package which might do the job for certain types of
applications as well.

Ciao,
Ingo
 
C

Chris Uppal

Gordon said:
You will have to call Free() explicitely. You can do that from a
finalizer, but IMO it's better to have an explicit dispose() method
that users of your class should call.

Agreed, although that isn't /always/ feasible[*].

However, even if it /is/ feasible, then I'd still recommend using a finalize()
method as a fallback cleanup method. Depending on your attitude and
application (and religion ;-) you might want to make the finalize() method
write an error report somewhere if it finds that the resource in question has
not been released already.

-- chris


[*] Basically[**] because it forces you to reason globally about object
lifetimes rather than locally -- that can make some application designs
unacceptably complicated and/or fragile, and may thus limit your design choices
unnecessarily.

[**] And also because it can be a right pain in the arse if your code makes
heavy use of the objects in question, and if the penalty for delaying
reclamation is small.
 
J

jan V

You will have to call Free() explicitely. You can do that from a
finalizer, but IMO it's better to have an explicit dispose() method
that users of your class should call.

With the emphasis on *should* (always, without fault), agreed.
 
O

Oliver Wong

Ingo R. Homann said:
Hi,



Although this is 100% correct, in practise the finalize-mechanism works
*much* better than it should do theoretically.

So, perhaps it is a good idea to go both ways: Explain the "users" that
they have to call it and call it in the finalizer as well. (Of course you
must ensure that there are no problems when dispose() is called twice.)

I think there's a common idiom for these kind of situations. Have the
finalizer call dispose (or have them both call a common 3rd private method).
Before doing the actual dispose, check a flag to see if it has already been
disposed. If not, do your disposing (in this case call "Free()") and then
set the flag.

From there, it's a design choice whether the second (or subsequent)
calls to dispose should be ignored, throw an exception or what. But with
this pattern, you'll never accidentally do the disposing twice.

- Oliver
 
J

John Smith

Thanks for your suggestions.

What I did was to make the Free() function available through the wrapper API
and then also add a finalize function:

protected void finalize()
{
Free();
}

My code already takes care of problems regarding calling it multiple times.
A handle is set to zero after first cleanup so on 2nd run it won't have any
effect.

What I did notice however is that it the finalize function doesn't
explicitly get called on application exit. I added a test printout and first
when I called System.runFinalizersOnExit(true) it worked.

Still it's something I will document so it should be ok.

-- John
 
T

Thomas Hawtin

John said:
What I did was to make the Free() function available through the wrapper API
and then also add a finalize function:

protected void finalize()
{
Free();
}

It's best if the finaliser method exactly match what is declared in
Object. Changing the exceptions thrown can disrupt subclasses. You
should call the super class' finaliser even if it redefine it. In any
case, it's better to move the finaliser to a guard object, so that it
doesn't become part of your interface and you are not dependent on any
subclasses calling their super.

public class MyResource {
private final Object guard = new Object() {
@Override
protected void finalize() throws Throwable {
Free();
super.finalize();
}
};
...
}

Tom Hawtin
 
C

Cantankerous Old Git

John said:
Thanks for your suggestions.

What I did notice however is that it the finalize function doesn't
explicitly get called on application exit. I added a test printout and first
when I called System.runFinalizersOnExit(true) it worked.

Well spotted. Not only is there no guarantee *when* a finalizer
will get called, there is no guarantee that it will *ever* be
called, especially in short-lived applications. This is why you
should never rely on the finalizer to switch off the whirling
blades or shut down the antimatter injectors.
 
T

Thomas G. Marshall

Chris Uppal coughed up:
Gordon said:
You will have to call Free() explicitely. You can do that from a
finalizer, but IMO it's better to have an explicit dispose() method
that users of your class should call.

Agreed, although that isn't /always/ feasible[*].

However, even if it /is/ feasible, then I'd still recommend using a
finalize() method as a fallback cleanup method. Depending on your
attitude and application (and religion ;-) you might want to make the
finalize() method write an error report somewhere if it finds that
the resource in question has not been released already.

-- chris


[*] Basically[**] because it forces you to reason globally about
object lifetimes rather than locally -- that can make some
application designs unacceptably complicated and/or fragile, and may
thus limit your design choices unnecessarily.

[**] And also because it can be a right pain in the arse if your code
makes heavy use of the objects in question, and if the penalty for
delaying reclamation is small.

No references to this last footnote. Should I read it? ;)
 
T

Thomas G. Marshall

Cantankerous Old Git coughed up:
Well spotted. Not only is there no guarantee *when* a finalizer
will get called, there is no guarantee that it will *ever* be
called, especially in short-lived applications. This is why you
should never rely on the finalizer to switch off the whirling
blades or shut down the antimatter injectors.

Love the emphasis. Very good way to put it. lol. If you /really/ want a
newbie to remember this with a visual, you might s/antimatter/enema.
 
V

Virgil Green

Thomas said:
Chris Uppal coughed up:
Gordon said:
You will have to call Free() explicitely. You can do that from a
finalizer, but IMO it's better to have an explicit dispose() method
that users of your class should call.

Agreed, although that isn't /always/ feasible[*].

However, even if it /is/ feasible, then I'd still recommend using a
finalize() method as a fallback cleanup method. Depending on your
attitude and application (and religion ;-) you might want to make the
finalize() method write an error report somewhere if it finds that
the resource in question has not been released already.

-- chris


[*] Basically[**] because it forces you to reason globally about
object lifetimes rather than locally -- that can make some
application designs unacceptably complicated and/or fragile, and may
thus limit your design choices unnecessarily.

[**] And also because it can be a right pain in the arse if your code
makes heavy use of the objects in question, and if the penalty for
delaying reclamation is small.

No references to this last footnote. Should I read it? ;)

Reference is in the first footnote.
 
T

Thomas G. Marshall

Virgil Green coughed up:
Thomas said:
Chris Uppal coughed up:
Gordon Beaton wrote:

You will have to call Free() explicitely. You can do that from a
finalizer, but IMO it's better to have an explicit dispose() method
that users of your class should call.

Agreed, although that isn't /always/ feasible[*].

However, even if it /is/ feasible, then I'd still recommend using a
finalize() method as a fallback cleanup method. Depending on your
attitude and application (and religion ;-) you might want to make
the finalize() method write an error report somewhere if it finds
that the resource in question has not been released already.

-- chris


[*] Basically[**] because it forces you to reason globally about
object lifetimes rather than locally -- that can make some
application designs unacceptably complicated and/or fragile, and may
thus limit your design choices unnecessarily.

[**] And also because it can be a right pain in the arse if your
code makes heavy use of the objects in question, and if the penalty
for delaying reclamation is small.

No references to this last footnote. Should I read it? ;)

Reference is in the first footnote.

{chuckle} ok. But footnotes should be optional reading. As such, if I punt
on the first....this is a WOT. Sorry. Thanks for pointing it out.
 
Joined
Sep 26, 2008
Messages
2
Reaction score
0
A related concept is implemented in org.springframework.util.WeakReferenceMonitor utility. It will create a weak reference to an object and invoke your callback method when the garbage collector determines that there are no more hard references to your object at which point you can free your JNI code. It is quite a simple piece of code using three java.lang.ref so you can copy the technique without having to ship the 2.5+m springframework jar with your app.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top