1 /*
   2  * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   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 G1AddMetaspaceDependency
  26  * @bug 8010196
  27  * @requires vm.gc=="G1" | vm.gc=="null"
  28  * @summary Checks that we don't get locking problems when adding metaspace dependencies with the G1 update buffer monitor
  29  * @run main/othervm -XX:+UseG1GC -XX:G1UpdateBufferSize=1 G1AddMetaspaceDependency
  30  */
  31 
  32 import java.io.InputStream;
  33 
  34 public class G1AddMetaspaceDependency {
  35 
  36   static byte[] getClassBytes(String name) {
  37     byte[] b = null;
  38     try (InputStream is = ClassLoader.getSystemResourceAsStream(name)) {
  39       byte[] tmp = new byte[is.available()];
  40       is.read(tmp);
  41       b = tmp;
  42     } finally {
  43       if (b == null) {
  44         throw new RuntimeException("Unable to load class file");
  45       }
  46       return b;
  47     }
  48   }
  49 
  50   static final String a_name = G1AddMetaspaceDependency.class.getName() + "$A";
  51   static final String b_name = G1AddMetaspaceDependency.class.getName() + "$B";
  52 
  53   public static void main(String... args) throws Exception {
  54     final byte[] a_bytes = getClassBytes(a_name + ".class");
  55     final byte[] b_bytes = getClassBytes(b_name + ".class");
  56 
  57     for (int i = 0; i < 1000; i += 1) {
  58       runTest(a_bytes, b_bytes);
  59     }
  60   }
  61 
  62   static class Loader extends ClassLoader {
  63     private final String myClass;
  64     private final byte[] myBytes;
  65     private final String friendClass;
  66     private final ClassLoader friendLoader;
  67 
  68     Loader(String myClass, byte[] myBytes,
  69            String friendClass, ClassLoader friendLoader) {
  70       this.myClass = myClass;
  71       this.myBytes = myBytes;
  72       this.friendClass = friendClass;
  73       this.friendLoader = friendLoader;
  74     }
  75 
  76     Loader(String myClass, byte[] myBytes) {
  77       this(myClass, myBytes, null, null);
  78     }
  79 
  80     @Override
  81     public Class<?> loadClass(String name) throws ClassNotFoundException {
  82       Class<?> c = findLoadedClass(name);
  83       if (c != null) {
  84         return c;
  85       }
  86 
  87       if (name.equals(friendClass)) {
  88         return friendLoader.loadClass(name);
  89       }
  90 
  91       if (name.equals(myClass)) {
  92         c = defineClass(name, myBytes, 0, myBytes.length);
  93         resolveClass(c);
  94         return c;
  95       }
  96 
  97       return findSystemClass(name);
  98     }
  99 
 100   }
 101 
 102   private static void runTest(final byte[] a_bytes, final byte[] b_bytes) throws Exception {
 103     Loader a_loader = new Loader(a_name, a_bytes);
 104     Loader b_loader = new Loader(b_name, b_bytes, a_name, a_loader);
 105     Loader c_loader = new Loader(b_name, b_bytes, a_name, a_loader);
 106     Loader d_loader = new Loader(b_name, b_bytes, a_name, a_loader);
 107     Loader e_loader = new Loader(b_name, b_bytes, a_name, a_loader);
 108     Loader f_loader = new Loader(b_name, b_bytes, a_name, a_loader);
 109     Loader g_loader = new Loader(b_name, b_bytes, a_name, a_loader);
 110 
 111     Class<?> c;
 112     c = b_loader.loadClass(b_name);
 113     c = c_loader.loadClass(b_name);
 114     c = d_loader.loadClass(b_name);
 115     c = e_loader.loadClass(b_name);
 116     c = f_loader.loadClass(b_name);
 117     c = g_loader.loadClass(b_name);
 118   }
 119   public class A {
 120   }
 121   class B extends A {
 122   }
 123 }