Yes but they could be referenced by an active Thread which itself is not referenced any more ... This entire chain of Object is not reachable anymore but is not yet ellegible for GC either as it's still referenced by an active Thread.
import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.spi.LoggingEvent;
/**
* This class tends to show that the <code>finalize</code>r are effectively
* run, but no <code>finalize</code>r of the unreachable chains of
* <code>Object</code>s are GCed.
*
* In its current state the program should not show anything in the console
*
* <pre>
* public class FinalizedClass
* {
* public Category log;
*
* public FinalizedClass ()
* {
* log = Category.getInstance(FinalizedClass.class);
* }
*
* public void finalize()
* {
* log.warn("finalize() run");
* }
* }
* </pre>
*
* The code has been successfully tested on the JDK's 1.2.2, 1.3, 1.4
*
* @author <a href="mailto:tsmets@lautre.net">Thomas SMETS</a>,
* this program can be copied as long as the name of the author is referenced.
* @version 0.3 - final
*
*/
public class ThreadedExampleWithoutGC
implements Runnable
{
public Category log;
public int i;
public static final int SLEEP_TIME = 1000;
public static final int SPAWN_EVERY = 10000;
public static final int ARRAY_SIZE = 10000;
ThreadedExampleWithoutGC (int i)
{
log = Category.getInstance(ThreadedExampleWithoutGC.class);
this.i = i;
log.info ("ThreadedExampleWithoutGC " + i + " created");
}
public void run()
{
int j = 0;
int k;
FinalizedClass o[];
while (true)
{
o = new FinalizedClass[ARRAY_SIZE]; // Allocate the space for the Object
try
{
log.info("Hi, I am " + i + " this is my " + j++ + "th loop");
for (k = 0; k < ARRAY_SIZE; k++)
o[k] = new FinalizedClass(); //
Thread.sleep(SLEEP_TIME);
}
catch (Exception ex)
{
log.warn("Ooops I got an exception", ex);
}
for (k = 0; k < ARRAY_SIZE; k++) // Simply dereferences the Custom Object
o[k] = null;
}
}
/**
* The provided implementation of the finalize method simply allow
* to put Logging statement in it !
*/
public void finalize ()
{
log.warn ("Running the finalizer for ThreadedExampleWithoutGC number " + this.i);
}
public static void main (String[] args)
throws Exception
{
int i = 0;
BasicConfigurator.resetConfiguration();
BasicConfigurator.configure(new CustomConsoleAppender(Priority.WARN));
System.runFinalization();
Thread t =null;
do // This "infinite" do-loop will generate java.lang.OutOfMemoryError
{ // The program is therefore bound to crash before some of
try // the finalizer are run
{
t = new Thread(new ThreadedExampleWithoutGC(i++));
t.start();
Thread.sleep(SPAWN_EVERY);
t = null; // To make sure that no reference to the active Thread still exist.
} catch (Exception ex)
{ // Just in case the System runs out of Memory
System.out.print("Exception " + ex.getClass());
}
} while (true);
} // End of main
/**
* This class is there simply to allow an <code>Object</code> finalization
* to be logged with its own <code>Level</code> and space of logging.
*/
public class FinalizedClass
{
public Category log;
public FinalizedClass ()
{
log = Category.getInstance(FinalizedClass.class);
}
public void finalize()
{
log.info("finalize() run");
}
} // End of inner class FinalizedClass
/**
*
* This class allows for a quickly <i>custom logging</i> to the Console.
* Any statement above the <code>Priority</code> level passed as
* argument ot the constructor will be given to the parent
* <code>ConsoleAppender</code> for Logging.
*
* I took this approache as I am not used to <code>PropertyConfigurator</code>,
* yet.
*
* (Inner) Class is <code>static</code> for simplicity's sake.
*
*/
static class CustomConsoleAppender
extends ConsoleAppender
{
Priority LoggingPriority = null;
CustomConsoleAppender(Priority aLoggingLevel)
{
LoggingPriority = aLoggingLevel;
}
public void doAppend(LoggingEvent aLoggingEvent)
{
if (aLoggingEvent.level.isGreaterOrEqual(LoggingPriority))
super.doAppend(aLoggingEvent);
return;
}
} // End of Inner class CustomConsoleAppender
} // End of Class
Program output should be
java.lang.OutOfMemoryError
<<no stack trace vailable>> java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
<<no stack trace available>>
Remark some statement have been removed for simplicity's sake.