7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @summary verify if the hidden class is unloaded when the class loader is GC'ed
27 * @library /test/lib/
28 * @build jdk.test.lib.util.ForceGC
29 * @run testng/othervm UnloadingTest
30 */
31
32 import java.io.IOException;
33 import java.lang.invoke.MethodHandles.Lookup;
34 import java.lang.ref.Reference;
35 import java.lang.ref.WeakReference;
36 import java.lang.reflect.Method;
37 import java.net.MalformedURLException;
38 import java.net.URL;
39 import java.net.URLClassLoader;
40 import java.nio.file.Files;
41 import java.nio.file.Path;
42 import java.nio.file.Paths;
43 import java.util.concurrent.atomic.AtomicInteger;
44
45 import jdk.test.lib.util.ForceGC;
46
89 * Test that a hidden class is not unloaded when the loader is strongly reachable
90 */
91 @Test
92 public void notUnloadable() throws Exception {
93 TestLoader loader = new TestLoader();
94 Class<?> helper = Class.forName("LookupHelper", true, loader);
95 Method m = helper.getMethod("getLookup");
96 Lookup lookup = (Lookup)m.invoke(null);
97 HiddenClassUnloader unloader = createHiddenClass(lookup, true);
98 assertFalse(unloader.tryUnload()); // hidden class is not unloaded
99
100 // loader is strongly reachable
101 Reference.reachabilityFence(loader);
102 }
103
104 /*
105 * Create a nest of two hidden classes.
106 * They can be unloaded even the loader is strongly reachable
107 */
108 @Test
109 public void hiddenClassNest2() throws Exception {
110 TestLoader loader = new TestLoader();
111 Class<?> helper = Class.forName("LookupHelper", true, loader);
112 Method m = helper.getMethod("getLookup");
113 Lookup lookup = (Lookup)m.invoke(null);
114 HiddenClassUnloader[] unloaders = createNestOfTwoHiddenClasses(lookup, false, false);
115
116 // keep a strong reference to the nest member class
117 Class<?> member = unloaders[1].weakRef.get();
118 // nest host and member will not be unloaded
119 assertFalse(unloaders[0].tryUnload());
120 assertFalse(unloaders[1].tryUnload());
121
122 // clear the reference to the nest member
123 member = null;
124
125 // nest host and member will be unloaded
126 unloaders[0].unload();
127 unloaders[1].unload();
128
129 // loader is strongly reachable
130 Reference.reachabilityFence(loader);
131 }
132
133 /*
134 * Create a nest with a hidden class nest host and strong nest member.
135 * Test that both are not unloaded
136 */
137 @Test
138 public void hiddenClassNestStrongMember() throws Exception {
139 TestLoader loader = new TestLoader();
140 Class<?> helper = Class.forName("LookupHelper", true, loader);
141 Method m = helper.getMethod("getLookup");
142 Lookup lookup = (Lookup)m.invoke(null);
189 Lookup hostLookup;
190 if (strongHost) {
191 hostLookup = lookup.defineHiddenClass(hiddenClassBytes, false, STRONG);
192 } else {
193 hostLookup = lookup.defineHiddenClass(hiddenClassBytes, false);
194 }
195 Class<?> host = hostLookup.lookupClass();
196 Class<?> member;
197 if (strongMember) {
198 member = hostLookup.defineHiddenClass(hiddenClassBytes, false, NESTMATE, STRONG).lookupClass();
199 } else {
200 member = hostLookup.defineHiddenClass(hiddenClassBytes, false, NESTMATE).lookupClass();
201 }
202 assertTrue(member.getNestHost() == host);
203 return new HiddenClassUnloader[] { new HiddenClassUnloader(host), new HiddenClassUnloader(member) };
204 }
205
206 static class HiddenClassUnloader {
207 private final WeakReference<Class<?>> weakRef;
208 private HiddenClassUnloader(Class<?> hc) {
209 assertTrue(hc.isHiddenClass());
210 this.weakRef = new WeakReference<>(hc);
211 }
212
213 void unload() {
214 // Force garbage collection to trigger unloading of class loader and native library
215 ForceGC gc = new ForceGC();
216 assertTrue(gc.await(() -> weakRef.get() == null));
217
218 if (weakRef.get() != null) {
219 throw new RuntimeException("loader " + " not unloaded!");
220 }
221 }
222
223 boolean tryUnload() {
224 ForceGC gc = new ForceGC();
225 return gc.await(() -> weakRef.get() == null);
226 }
227 }
228
229 static class TestLoader extends URLClassLoader {
|
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @summary verify if the hidden class is unloaded when the class loader is GC'ed
27 * @modules jdk.compiler
28 * @library /test/lib/
29 * @build jdk.test.lib.util.ForceGC
30 * @run testng/othervm UnloadingTest
31 */
32
33 import java.io.IOException;
34 import java.lang.invoke.MethodHandles.Lookup;
35 import java.lang.ref.Reference;
36 import java.lang.ref.WeakReference;
37 import java.lang.reflect.Method;
38 import java.net.MalformedURLException;
39 import java.net.URL;
40 import java.net.URLClassLoader;
41 import java.nio.file.Files;
42 import java.nio.file.Path;
43 import java.nio.file.Paths;
44 import java.util.concurrent.atomic.AtomicInteger;
45
46 import jdk.test.lib.util.ForceGC;
47
90 * Test that a hidden class is not unloaded when the loader is strongly reachable
91 */
92 @Test
93 public void notUnloadable() throws Exception {
94 TestLoader loader = new TestLoader();
95 Class<?> helper = Class.forName("LookupHelper", true, loader);
96 Method m = helper.getMethod("getLookup");
97 Lookup lookup = (Lookup)m.invoke(null);
98 HiddenClassUnloader unloader = createHiddenClass(lookup, true);
99 assertFalse(unloader.tryUnload()); // hidden class is not unloaded
100
101 // loader is strongly reachable
102 Reference.reachabilityFence(loader);
103 }
104
105 /*
106 * Create a nest of two hidden classes.
107 * They can be unloaded even the loader is strongly reachable
108 */
109 @Test
110 public void hiddenClassNest() throws Exception {
111 TestLoader loader = new TestLoader();
112 Class<?> helper = Class.forName("LookupHelper", true, loader);
113 Method m = helper.getMethod("getLookup");
114 Lookup lookup = (Lookup)m.invoke(null);
115 HiddenClassUnloader[] unloaders = createNestOfTwoHiddenClasses(lookup, false, false);
116
117 // keep a strong reference to the nest member class
118 Class<?> member = unloaders[1].weakRef.get();
119 assertTrue(member != null);
120 // nest host and member will not be unloaded
121 assertFalse(unloaders[0].tryUnload());
122 assertFalse(unloaders[1].tryUnload());
123
124 // clear the reference to the nest member
125 Reference.reachabilityFence(member);
126 member = null;
127
128 // nest host and member will be unloaded
129 unloaders[0].unload();
130 unloaders[1].unload();
131
132 // loader is strongly reachable
133 Reference.reachabilityFence(loader);
134 }
135
136 /*
137 * Create a nest with a hidden class nest host and strong nest member.
138 * Test that both are not unloaded
139 */
140 @Test
141 public void hiddenClassNestStrongMember() throws Exception {
142 TestLoader loader = new TestLoader();
143 Class<?> helper = Class.forName("LookupHelper", true, loader);
144 Method m = helper.getMethod("getLookup");
145 Lookup lookup = (Lookup)m.invoke(null);
192 Lookup hostLookup;
193 if (strongHost) {
194 hostLookup = lookup.defineHiddenClass(hiddenClassBytes, false, STRONG);
195 } else {
196 hostLookup = lookup.defineHiddenClass(hiddenClassBytes, false);
197 }
198 Class<?> host = hostLookup.lookupClass();
199 Class<?> member;
200 if (strongMember) {
201 member = hostLookup.defineHiddenClass(hiddenClassBytes, false, NESTMATE, STRONG).lookupClass();
202 } else {
203 member = hostLookup.defineHiddenClass(hiddenClassBytes, false, NESTMATE).lookupClass();
204 }
205 assertTrue(member.getNestHost() == host);
206 return new HiddenClassUnloader[] { new HiddenClassUnloader(host), new HiddenClassUnloader(member) };
207 }
208
209 static class HiddenClassUnloader {
210 private final WeakReference<Class<?>> weakRef;
211 private HiddenClassUnloader(Class<?> hc) {
212 assertTrue(hc.isHidden());
213 this.weakRef = new WeakReference<>(hc);
214 }
215
216 void unload() {
217 // Force garbage collection to trigger unloading of class loader and native library
218 ForceGC gc = new ForceGC();
219 assertTrue(gc.await(() -> weakRef.get() == null));
220
221 if (weakRef.get() != null) {
222 throw new RuntimeException("loader " + " not unloaded!");
223 }
224 }
225
226 boolean tryUnload() {
227 ForceGC gc = new ForceGC();
228 return gc.await(() -> weakRef.get() == null);
229 }
230 }
231
232 static class TestLoader extends URLClassLoader {
|