[1977] in java-interest

home help back first fref pref prev next nref lref last post

Re: Question on circular linked lists

daemon@ATHENA.MIT.EDU (Chuck McManis)
Wed Sep 20 19:27:56 1995

Date: Wed, 20 Sep 1995 13:57:49 -0700
From: cmcmanis@scndprsn.Eng.Sun.COM (Chuck McManis)
To: java-interest@java.Eng.Sun.COM, sasebb@unx.sas.com


>Suppose that you have a circularly linked list. Wouldn't it be
>possible to orphan this memory and have a memory leak,
>since nulling the master pointer wouldn't decrement the use
>count to zero, and it would seem impractical for the system
>to check for loops in the reference chains.

Nope, we do mark and sweep, not reference counting. As an experiment
you can do something like this, Here is a class that implements a
simple linked list:

class LinkedList {
    LinkedList next;
    LinkedList prev;
    String name;

    public LinkedList(String x) {
	name = x;
    }

    public String toString() {
	return ("LinkedList: " + name);
    }

    void finalize() {
	System.out.println(name+" is being collected.");
    }
}

Now it defines very simple nodes that have a "name" associated with them
a method to print them, and a "finalize" method. Now normally the finalize
method is used to allow us to clean up resources however we'll just use
it to announce that we've been garbage collected.

Now you can test it with this class :
public class LinkTest {
    static LinkedList head = null;

    static String names[] = {
	"Curly",
	"Moe",
	"Joe",
	"Bugs",
	"Tweety",
	"Sylvester" };

    public static void main(String args[]) {
	LinkedList x;

	for (int i = 0; i < names.length; i++) {
	    x = new LinkedList(names[i]);
	    if (head != null) {
		x.next = head.next;
		head.next = x;
		x.prev = head;
		head = x;
	    } else {
	    	head = x;
		x.next = x;
		x.prev = x;
	    }
	}

	// demonstrate we do in fact have a circularly linked list.
	x = head;
	for (int i = 0; i < 16; i ++) {
	    System.out.println("["+i+"] - "+x);
	    x = x.next;
	}

	// run the garbage collector (no effect since we're holding ptrs)
	System.out.println("Kicking off a gc()");
	System.gc();
	System.out.println("Going to sleep to let finalization run.");
	try {
	    Thread.currentThread().sleep(5000);
	} catch (InterruptedException e) {}

	// drop the pointer to the head of the list and x the last node.
	System.out.println("Done, dropping pointers...");
	x = null;
	head = null;

	// Run GC again, this puts these objects in the finalize queue
	System.out.println("Done, doing another GC ");
	System.gc();
	System.out.println("Going to sleep to let finalization run.");
	try {
	    Thread.currentThread().sleep(5000);
	} catch (InterruptedException e) {}
    }
}

Now the output is simply:
java -cs LinkTest
[0] - LinkedList: Sylvester
[1] - LinkedList: Curly
[2] - LinkedList: Moe
[3] - LinkedList: Joe
[4] - LinkedList: Bugs
[5] - LinkedList: Tweety
[6] - LinkedList: Sylvester
[7] - LinkedList: Curly
[8] - LinkedList: Moe
[9] - LinkedList: Joe
[10] - LinkedList: Bugs
[11] - LinkedList: Tweety
[12] - LinkedList: Sylvester
[13] - LinkedList: Curly
[14] - LinkedList: Moe
[15] - LinkedList: Joe
Kicking off a gc()
Going to sleep to let finalization run.
Done, now dropping reference pointers...
Done, doing another GC 
Going to sleep to let finalization run.
Curly is being collected.
Moe is being collected.
Joe is being collected.
Bugs is being collected.
Tweety is being collected.
Sylvester is being collected.

Where you can see that the entire list gets collected there after we've
dropped the pointers too it.

--Chuck
-
Note to Sun employees: this is an EXTERNAL mailing list!
Info: send 'help' to java-interest-request@java.sun.com

home help back first fref pref prev next nref lref last post