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