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