forcing finalize()

C

cy

I found way to force finalize() using deprecated since JDK 1.1 method:

--------------------------------------------------------------------------
class WebBank {
boolean loggedIn = false;
WebBank(boolean logStatus) {
loggedIn = logStatus;
}
void logOut() {
loggedIn = false;
}
protected void finalize() {
if(loggedIn)
System.out.println("Error: still logged in");
// Normally, you'll also call the base-class version:
// super.finalize();
}
}
public class BankTest {
public static void main(String[] args) {
WebBank bank1 = new WebBank(true);
WebBank bank2 = new WebBank(true);
new WebBank(true);
// Proper cleanup: log out of bank1 before going home:
bank1.logOut();
// Forget to logout of bank2 and unnamed new bank
// Attempts to finalize any missed banks:
System.out.println("Try 1: ");
System.runFinalization();
System.out.println("Try 2: ");
Runtime.getRuntime().runFinalization();
System.out.println("Try 3: ");
System.gc();
System.out.println("Try 4: ");
System.runFinalizersOnExit(true);
}
}
------------------------------------------------------------------
output:
Try 1:
Try 2:
Try 3:
Try 4:
Error: still logged in
Error: still logged in
 
C

Chris Uppal

cy said:
I found way to force finalize() using deprecated since JDK 1.1 method:

It's deprecated, and for good reason -- don't use it.

If you want to ensure cleanup on exit then there is a framework for that: see
Runtime.addShutdownHook().

You'd create a list somewhere of the "things" that needed to be cleaned up, and
your shutdown hook would loop over that list doing <something> to each "thing".
If you want earlier cleanup either explicitly, or via finalisation, then the
you explicitly /remove/ the corresponding "thing" from the list as you clean
them up.

Or so I'm told -- I have never once needed to use this feature myself.

-- chris
 
R

Robert Klemme

only deprecated runFinalizersOnExit() method worked!
why not the others? even System.gc()?
any other non-deprecated way to force finalization?

Finalization is not guaranteed. You cannot rely on it to happen. Even
if you could there is the issue of making an instance reachable in the
finalizer which will not result in a second invocation of the finalizer
once the object becomes collectible again.

Also, I believe there is a performance penalty paid for classes with
finalizers.

To make a long story short, you probably should not rely on finalizers
for cleanup. Using finally blocks has some advantages: the code is
always executed and it is typically executed much earlier than a
finalizer would.

Kind regards

robert
 
N

nukleus

Robert Klemme said:
Finalization is not guaranteed. You cannot rely on it to happen. Even
if you could there is the issue of making an instance reachable in the
finalizer which will not result in a second invocation of the finalizer
once the object becomes collectible again.

Also, I believe there is a performance penalty paid for classes with
finalizers.

To make a long story short, you probably should not rely on finalizers
for cleanup. Using finally blocks has some advantages: the code is
always executed and it is typically executed much earlier than a
finalizer would.

Interesting idea.

Btw, I just read some posts on memory allocation/deallocation issues,
and I did not quite expect the behavior described.

I thought that object is gc'ed when there are no references left.

So, if i have a multi-variable object, containing strings,
buffers, etc. and I put those objects in a Vector,
for the sake of argument, and, i do setElementAt() and set
it to null, i thought it becomes a subject to gc,
and, once it is gc'ed, all the buffers, strings, etc.,
it contains become subject to gc also.

Is that true?

Secondly, if i have a string and then set it to a new value,
does the old value become a subject to gc?

Sting s = "abc";
s = "def";

What happens to "abc" string in terms of deallocation?
Is it the same as new String("def")
meaning that there is no longer a reference
to "abc" and it, therefore, is subject to gc?

How do I release memory held by StringBuffer?
When I set its size to 0 and start accumulating
a new data in it, what happens to the old data?
Is it gc'ed?

Intuitively, it seems that by merely doing setLength
to 0, it should not change anything as the reference
is effectively still there, as what StringBuffer looks
to me is what is known as counted string versus C string.

Can you clarify this issue?

Thanks.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

nukleus said:
Btw, I just read some posts on memory allocation/deallocation issues,
and I did not quite expect the behavior described.

I thought that object is gc'ed when there are no references left.

Java does not use reference counting.

Objects that are not reachable from the executing program can be
GC'ed.
So, if i have a multi-variable object, containing strings,
buffers, etc. and I put those objects in a Vector,
for the sake of argument, and, i do setElementAt() and set
it to null, i thought it becomes a subject to gc,
and, once it is gc'ed, all the buffers, strings, etc.,
it contains become subject to gc also.

The GC can/should GC them all in one sweep.
Secondly, if i have a string and then set it to a new value,
does the old value become a subject to gc?
Yes.

Sting s = "abc";
s = "def";

There are some special handling for string literals where Java
only have one object for the same literal.
What happens to "abc" string in terms of deallocation?
Is it the same as new String("def")
meaning that there is no longer a reference
to "abc" and it, therefore, is subject to gc?

Ignoring the special handling of String literals, then
as soon as there are no way to reach an object it can be GC'ed.
How do I release memory held by StringBuffer?

Just let the reference run out of scope.
When I set its size to 0 and start accumulating
a new data in it, what happens to the old data?
Is it gc'ed?

Depends on the implementation. You can look it up whether
it reuses the backing storage or not. I have not checked
it out myself. You should not code after that kind of
implementation issues.

Arne
 
N

nukleus

Java does not use reference counting.

Objects that are not reachable from the executing program can be
GC'ed.

Interesting. But how do they know they are not reachable?
The GC can/should GC them all in one sweep.

Thanks god.
There are some special handling for string literals where Java
only have one object for the same literal.

Well, i didn't mean string literal,
but string as such.
Ignoring the special handling of String literals, then
as soon as there are no way to reach an object it can be GC'ed.

Sorry, but I don't get it.
How does it know it can't reach something?
Just let the reference run out of scope.

Well, but when I am in a loop, reusing the same string
buffer that has large amounts of buffer for each iteration,
what happens to the old data?
Should I just create a new buffer every iteration
just to make sure the old stuff gets gc'ed?
I am talking about 10s of megs of data being shuffled.
 
E

Eric Sosman

nukleus said:
Interesting. But how do they know they are not reachable?

"They" the objects don't know. The garbage collector
works hard to find out.
Well, i didn't mean string literal,
but string as such.

Any object instance that is unreachable by a chain of
sufficiently strong references[*] is eligible for garbage
collection.

[*] To support caches of various kinds, Java provides
some specialized weaker-than-normal reference types. I'm
not familiar with the ins and outs of all of them: weak
references, phantom references, unsubstantiated references,
unattributed references (a.k.a. plagiarism), and whatever
other flavors might exist. Some of these are too weak to
shield an instance from garbage collection, yet strong
enough to locate it if the collector hasn't reaped it first.
It's my understanding that String.intern() uses one of these
weaker forms, so even a String[**] literal could perhaps be
collected. (Probably not unless all the classes that contain
it are also collected, but I believe it's possible nonetheless.)

[**] I don't know what happens to Sting objects.
Sorry, but I don't get it.
How does it know it can't reach something?

The garbage collector begins from a set of known "root"
references, and finds other references (or possible references)
in the Thread stacks. Then it follows all these references to
their referenced objects, and follows all the references found
inside those objects, and so on, until it's located every object
that is referencable. Everything not located is unreachable and
hence garbage, eligible for collection.

The details of how this search is carried out vary from one
implementation to another. I believe there's still a lot of
active research on how to make GC pleasanter in various ways.
Well, but when I am in a loop, reusing the same string
buffer that has large amounts of buffer for each iteration,
what happens to the old data?
Should I just create a new buffer every iteration
just to make sure the old stuff gets gc'ed?
I am talking about 10s of megs of data being shuffled.

For specificity, let's consider two different loops:

// Loop A
StringBuffer buff = new StringBuffer();
for (...) {
buff.setLength(0);
... fill up buff and use it ...
}

// Loop B
for (...) {
StringBuffer buff = new StringBuffer();
... fill up buff and use it ...
}

Loop A uses the same StringBuffer over and over, changing its
contents each time around. Loop B creates a fresh StringBuffer
at each iteration. Which is more efficient? Much depends on
the nature of "use it." For example, if you "use it" by making
a String out of it, the String seizes ownership of the underlying
char[] array and retains it until the String itself becomes garbage.
In this (common) case, the only memory you're "recycling" are the
dribs and drabs that give a StringBuffer its StringBuffer-nature,
not the zillions of megabytes of character data its various
incarnations contain. On the other hand, if you work entirely
within the StringBuffer and never generate a String from it, the
multimegs may well be recycled by Loop A, garbage-collected by
Loop B.
 
C

Chris Uppal

Eric said:
weak
references, phantom references, unsubstantiated references,
unattributed references (a.k.a. plagiarism), and [...]

<loud grin/>

Nothing to add, but I couldn't let it pass without acknowledgement.

-- chris
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

nukleus said:
Interesting. But how do they know they are not reachable?

Sorry, but I don't get it.
How does it know it can't reach something?

The GC is a smart guy.

:)

But if you consider it, then you will find that you can do
it manually. And if you can do it manually there are a good
possibility that you can write code to do the same.

And they have to it that way.

Reference counting almost always lead to memory leaks,
because two unreachable objects have a reference to each other.

Arne
 
O

Oliver Wong

Arne Vajhøj said:
The GC is a smart guy.

There are many techniques, and it *is* a domain of active research, and
it *is* relatively complicated. Do some google queries (e.g. "garbage
collection") and I'm sure you'll find some published articles and research
papers on various GC algorithms. Or contact your local university -- perhaps
a local computer science professor can direct you to some textbooks on the
subject.

- Oliver
 

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