public class testGC {
    public static String objId (Object obj) {
	return obj + "/"
	    + Integer.toHexString(obj.getClass().getClassLoader().hashCode());
    }
    public static class cld extends java.net.URLClassLoader {
	static Object obj = new cl0();
	public cld () throws Exception {
	    super(new java.net.URL[] { new java.net.URL("file://./") });
	    System.out.println (objId (this) + " created");
	}
	public void finalize () {
	    System.out.println (objId (this) + " finalized");
	}
	public String toString () {
	    return this.getClass().getName() + "@"
		+ Integer.toHexString (hashCode ());
	}
	public Class loadClass (String name) throws ClassNotFoundException {
	    try {
		java.io.InputStream IS = getResourceAsStream (name + ".class");
		int maxsz = 1, readsz = 0;
		byte buf[] = new byte[maxsz];
		for(;;) {
		    int readnow = IS.read (buf, readsz, maxsz - readsz);
		    if (readnow <= 0)
			break;
		    readsz += readnow;
		    if (readsz == maxsz) {
			byte newbuf[] = new byte[maxsz *= 2];
			System.arraycopy (buf, 0, newbuf, 0, readsz);
			buf = newbuf;
		    }
		}
		return defineClass (name, buf, 0, readsz);
	    } catch (Exception e) {
		return super.loadClass (name);
	    }
	}
    }
    public static class cl0 {
	public cl0 () {
	    System.out.println (objId (this) + " created");
	}
	public void finalize () {
	    System.out.println (objId (this) + " finalized");
	}
    }
    public static class cl1 {
	static Object obj = new cl0();
	public cl1 () {
	    System.out.println (objId (this) + " created");
	}
	public void finalize () {
	    System.out.println (objId (this) + " finalized");
	}
    }
    public static class cl2 {
	static Object obj = new cl0();
	public cl2 () {
	    System.out.println (objId (this) + " created");
	}
	public void finalize () {
	    System.out.println (objId (this) + " finalized");
	}
    }
    static Object obj = new cl0();
    public static void main(String[] argv) throws Exception {
	new cld().loadClass ("testGC$cl1").newInstance ();
	new cld().loadClass ("testGC$cl2").newInstance ();
	new cld().loadClass ("testGC$cl1").newInstance ();
	new cld().loadClass ("testGC$cl2").newInstance ();
	for (int i = 1; i <= 8; i++) {
	    System.out.println ("Will run GC and finalization " + i);
	    System.gc ();
	    Thread.yield ();
	    System.runFinalization ();
	    Thread.yield ();
	}
    }
}
