1 /* Verify that libffi closures aren't deallocated too early.
2 
3    Copyright (C) 2007 Free Software Foundation, Inc
4    Contributed by Alexandre Oliva <aoliva@redhat.com>
5 
6    If libffi closures are released too early, we lose.
7  */
8 
9 import java.util.HashSet;
10 
11 public class TestClosureGC {
objId(Object obj)12     public static String objId (Object obj) {
13 	return obj + "/"
14 	    + Integer.toHexString(obj.getClass().getClassLoader().hashCode());
15     }
16     public static class cld extends java.net.URLClassLoader {
17 	static final Object obj = new cl0();
cld()18 	public cld () throws Exception {
19 	    super(new java.net.URL[] { });
20 	    /* System.out.println (objId (this) + " created"); */
21 	}
finalize()22 	public void finalize () {
23 	    /* System.out.println (objId (this) + " finalized"); */
24 	}
toString()25 	public String toString () {
26 	    return this.getClass().getName() + "@"
27 		+ Integer.toHexString (hashCode ());
28 	}
loadClass(String name)29 	public Class loadClass (String name) throws ClassNotFoundException {
30 	    try {
31 		java.io.InputStream IS = getSystemResourceAsStream
32 		    (name + ".class");
33 		int maxsz = 1024, readsz = 0;
34 		byte buf[] = new byte[maxsz];
35 		for(;;) {
36 		    int readnow = IS.read (buf, readsz, maxsz - readsz);
37 		    if (readnow <= 0)
38 			break;
39 		    readsz += readnow;
40 		    if (readsz == maxsz) {
41 			byte newbuf[] = new byte[maxsz *= 2];
42 			System.arraycopy (buf, 0, newbuf, 0, readsz);
43 			buf = newbuf;
44 		    }
45 		}
46 		return defineClass (name, buf, 0, readsz);
47 	    } catch (Exception e) {
48 		return super.loadClass (name);
49 	    }
50 	}
51     }
52     public static class cl0 {
cl0()53 	public cl0 () {
54 	    /* System.out.println (objId (this) + " created"); */
55 	}
finalize()56 	public void finalize () {
57 	    /* System.out.println (objId (this) + " finalized"); */
58 	}
59     }
60     public static class cl1 {
61 	final HashSet hs;
62 	static final Object obj = new cl0();
cl1(final HashSet hs)63 	public cl1 (final HashSet hs) {
64 	    this.hs = hs;
65 	    /* System.out.println (objId (this) + " created"); */
66 	}
finalize()67 	public void finalize () {
68 	    /* System.out.println (objId (this) + " finalized"); */
69 	}
70     }
71     public static class cl2 {
72 	final HashSet hs;
73 	static final Object obj = new cl0();
cl2(final HashSet hs)74 	public cl2 (final HashSet hs) {
75 	    this.hs = hs;
76 	    /* System.out.println (objId (this) + " created"); */
77 	}
finalize()78 	public void finalize () {
79 	    /* System.out.println (objId (this) + " finalized"); */
80 	    hs.add(this);
81 	    hs.add(new cl0());
82 	}
83     }
84     static final HashSet hs = new HashSet();
85     static final Object obj = new cl0();
main(String[] argv)86     public static void main(String[] argv) throws Exception {
87 	{
88 	    Class[] hscs = { HashSet.class };
89 	    Object[] hsos = { hs };
90 	    new cld().loadClass ("TestClosureGC$cl1").
91 		getConstructor (hscs).newInstance (hsos);
92 	    new cld().loadClass ("TestClosureGC$cl2").
93 		getConstructor (hscs).newInstance (hsos);
94 	    new cld().loadClass ("TestClosureGC$cl1").
95 		getConstructor (hscs).newInstance (hsos);
96 	    new cld().loadClass ("TestClosureGC$cl1").
97 		getConstructor (hscs).newInstance (hsos);
98 	}
99 	for (int i = 1; i <= 5; i++) {
100 	    /* System.out.println ("Will run GC and finalization " + i); */
101 	    System.gc ();
102 	    Thread.sleep (100);
103 	    System.runFinalization ();
104 	    Thread.sleep (100);
105 	    if (hs.isEmpty ())
106 		continue;
107 	    java.util.Iterator it = hs.iterator ();
108 	    while (it.hasNext ()) {
109 		Object obj = it.next();
110 		/* System.out.println (objId (obj) + " in ht, removing"); */
111 		it.remove ();
112 	    }
113 	}
114 	System.out.println ("ok");
115     }
116 }
117