Question on finalize method

A

ankur

Can objects be garbage collected without calling finalize ? How does
that work ?

In this code finalize was called once and exceptions were thrown and
so objects remained eligible and were not garbage collected. Next time
however the objects were garbage collected without calling finalize
( because finalize is only called once on an object).

package pack4;

class HeavyClass
{
long[] arr = new long[100000];
public void finalize() throws Throwable
{

System.out.println("In finalize");
throw new Throwable();

}
}

public class FinalizerCheck
{
public static void main(String[] args)
{
System.out.println(Runtime.getRuntime().freeMemory());
HeavyClass obj1 = new HeavyClass();
HeavyClass obj2 = new HeavyClass();
HeavyClass obj3 = new HeavyClass();
System.out.println(Runtime.getRuntime().freeMemory());
obj1 = null; obj2 = null; obj3 = null;
System.gc();

try
{
Thread.sleep(5000);
}
catch(Exception e)
{}
System.out.println(Runtime.getRuntime().freeMemory()); //3
System.gc();
System.out.println(Runtime.getRuntime().freeMemory());
}
}

Sample output :

4993000
2666136
In finalize
In finalize
In finalize
2638256 //3
5066280 //4

notice that 3 indicates the objects are not garbage collected first
time around but at 4 they are garbage collected without calling
finalize .
 
L

Lew

ankur said:
Can objects be garbage collected without calling finalize ? How does
that work ?

Strictly speaking, no, but if the 'finalize()' method has not been overridden
from 'Object' then effectively you GC objects without calling it. This is
called having a "trivial finalizer".

If you have a non-trivial finalizer, i.e., it's overridden, then it takes a
minimum of two GC cycles to reclaim an object's memory, instead of the one it
might take with a trivial finalizer.
In this code finalize was called once and exceptions were thrown and
so objects remained eligible and were not garbage collected. Next time
however the objects were garbage collected without calling finalize
( because finalize is only called once on an object). ....
notice that 3 indicates the objects are not garbage collected first
time around but at 4 they are garbage collected without calling
finalize .

The JLS speaks to this, of course:
<http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.6>

'finalize()' is called at most once, after which the object is noted as
/finalized/. Ss. 12.6.1 discusses the details.

Joshua Bloch has much to say on the subject:
<http://java.sun.com/docs/books/effective/>
Item 7: "Avoid Finalizers"

Brian Goetz says "Finalizers are not your friend" in
Objects with finalizers (those that have a non-trivial finalize() method)
have significant overhead compared to objects without finalizers, and
should be used sparingly. Finalizeable objects are both slower to allocate
and slower to collect.

That same article dispels various myths about "helping" GC, highlighting for
example the inadvisability of nulling references willy-nilly and of
System.gc() calls.
 
J

Joshua Cranmer

ankur said:
Can objects be garbage collected without calling finalize ? How does
that work ?

finalize() is evil.

Actually, from what I recall of previous discussions of GC, finalize()
is not called for classes if its definition is the trivial one, i.e. it
just inherits one from Object.
4993000
2666136
In finalize
In finalize
In finalize
2638256 //3
5066280 //4

notice that 3 indicates the objects are not garbage collected first
time around but at 4 they are garbage collected without calling
finalize .

You're misinterpreting what goes on.

In the first garbage collection run, the garbage collector determined
that the objects could be reclaimed by virtue of having no references.
When it started, it detected finalize() and therefore ran it, but it
/did not reclaim the objects/ (key point there!). After running it, it
marked the object as finalized and shelved it for the next run. When it
did the next run, it noted that the objects had no references and were
already finalized, so it actually reclaimed the objects.

That is why finalize() is evil. Since it can cause the class to gain a
new reference, it opens up powerful edge cases in the garbage
collectors. It also requires that the garbage collector call the method
before it can actually reclaim memory.
 
L

Lew

Joshua said:
finalize() is evil.

Actually, from what I recall of previous discussions of GC, finalize()
is not called for classes if its definition is the trivial one, i.e. it
just inherits one from Object.

This corrects what I said in error upthread. The JVM notes if Object's
finalize() is overridden (or, for some JVMs, only trivially overridden),
otherwise it doesn't call finalize().

This explains why allocation is slower for non-trivial-finalizer objects than
for trivial-finalizer ones. It takes work at allocation for the JVM to mark
an object as having a non-trivial finalizer.
 
J

Joshua Cranmer

Lew said:
That same article dispels various myths about "helping" GC, highlighting
for example the inadvisability of nulling references willy-nilly and of
System.gc() calls.

Or, my favorite catch-phrase w.r.t. the garbage collector:

Don't try to outwit the garbage collector. It can do its job just fine
without you having to tell it what to do.
 
M

Mike Schilling

Joshua said:
Or, my favorite catch-phrase w.r.t. the garbage collector:

Don't try to outwit the garbage collector. It can do its job just
fine
without you having to tell it what to do.

Except when it can't, and then there's usually not a dammed thing you
can do about it.
 
M

Mike Schilling

Lew said:
This corrects what I said in error upthread. The JVM notes if
Object's finalize() is overridden (or, for some JVMs, only trivially
overridden), otherwise it doesn't call finalize().

This explains why allocation is slower for non-trivial-finalizer
objects than for trivial-finalizer ones. It takes work at
allocation
for the JVM to mark an object as having a non-trivial finalizer.

Really? I'd think the class would be marked as having a non-trivial
finalizer, not each instance of it.
 
L

Lew

Mike said:
Really? I'd think the class would be marked as having a non-trivial
finalizer, not each instance of it.

The JVM has to mark individual objects because it's the objects that get
finalized and collected. This marking happens during object allocation.

From
 
M

Mike Schilling

Lew said:
The JVM has to mark individual objects because it's the objects that
get finalized and collected.

Sure, but each object points directly to its Class's object (in any
JVM implementation I know of, anyway.) Traversing object->Class to
check properties like "requiresFinalization" makes more sense than
storing that flag in each object.
This marking happens during object allocation. From

Ah. I suspect this means that the GC keeps a list of finalizeable
objects.
 
L

Lew

Mike said:
Sure, but each object points directly to its Class's object (in any
JVM implementation I know of, anyway.) Traversing object->Class to
check properties like "requiresFinalization" makes more sense than
storing that flag in each object.


Ah. I suspect this means that the GC keeps a list of finalizeable
objects.

That's what I said. It's certainly what Mr. Goetz said, and proves that the
JVM marks individual objects as needing finalization, as averred.
 
M

Mike Schilling

Lew said:
That's what I said. It's certainly what Mr. Goetz said, and proves
that the JVM marks individual objects as needing finalization, as
averred.

Perhaps I took "marks individual objects" too literally, as meaning a
mark *contained within* the object.

Also consider that, in many GCs, most objects are assumed to be
short-lived (that is, likely not to survive the next GC), and their
allocation is optimized based on that assumption. Finalizeable
objects are necessarily longer-lived than that, since the first GC at
most marks them as ready for finalization. That's another reason,
besides the need to keep track of them individually, that
finalizeable objects must follow a slower allocation path.
 
L

Lew

Mike said:
Perhaps I took "marks individual objects" too literally, as meaning a
mark *contained within* the object.

From <http://en.wiktionary.org/wiki/mark>:
1. To indicate in some way for later reference.
2. To take note of.

Neither of the first two listed literal meanings for the verb denotes making a
mark on the thing itself. Both apply to what the JVM does with objects that
need finalization on deallocation.
 

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

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top