< prev index next >

test/jdk/java/lang/invoke/defineHiddenClass/UnloadingTest.java

Print this page
rev 58565 : 8238358: Implementation of JEP 371: Hidden Classes
Reviewed-by: duke
Contributed-by: mandy.chung@oracle.com, lois.foltan@oracle.com, david.holmes@oracle.com, harold.seigel@oracle.com, serguei.spitsyn@oracle.com, alex.buckley@oracle.com, jamsheed.c.m@oracle.com
rev 58568 : [mq]: hidden-class-4


   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 {
< prev index next >