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 package utils;
24
25 import java.io.*;
26 import java.util.*;
27
28 /**
29 * Classloader that generates classes on the fly.
30 *
31 * This classloader can load classes with name starting with 'Class'. It will
32 * use TemplateClass as template and will replace class name in the bytecode of
33 * template class. It can be used for example to detect memory leaks in class
34 * loading or to quickly fill PermGen.
35 */
36 class GeneratingClassLoader extends ClassLoader {
37
38 public synchronized Class loadClass(String name) throws ClassNotFoundException {
39 return loadClass(name, false);
40 }
41
42 public synchronized Class loadClass(String name, boolean resolve)
43 throws ClassNotFoundException {
44 Class c = findLoadedClass(name);
45 if (c != null) {
46 return c;
47 }
48 if (!name.startsWith(PREFIX)) {
49 return super.loadClass(name, resolve);
50 }
51 if (name.length() != templateClassName.length()) {
52 throw new ClassNotFoundException("Only can load classes with name.length() = " + getNameLength() + " got: '" + name + "' length: " + name.length());
53 }
54 byte[] bytecode = getPatchedByteCode(name);
55 c = defineClass(name, bytecode, 0, bytecode.length);
56 if (resolve) {
57 resolveClass(c);
58 }
59 return c;
60 }
61
62 /**
63 * Create generating class loader that will use class file for given class
64 * from classpath as template.
65 */
66 GeneratingClassLoader(String templateClassName) {
67 this.templateClassName = templateClassName;
68 classPath = System.getProperty("java.class.path").split(File.pathSeparator);
69 try {
70 templateClassNameBytes = templateClassName.getBytes(encoding);
71 } catch (UnsupportedEncodingException e) {
72 throw new RuntimeException(e);
73 }
74 }
75
76 /**
77 * Create generating class loader that will use class file for
78 * nsk.share.classload.TemplateClass as template.
79 */
80 GeneratingClassLoader() {
81 this(TemplateClass.class.getName());
82 }
83
84 int getNameLength() {
85 return templateClassName.length();
86 }
87
88 String getPrefix() {
89 return PREFIX;
90 }
91
92 String getClassName(int number) {
93 StringBuffer sb = new StringBuffer();
94 sb.append(PREFIX);
95 sb.append(number);
96 int n = templateClassName.length() - sb.length();
97 for (int i = 0; i < n; ++i) {
98 sb.append("_");
99 }
100 return sb.toString();
101 }
102
103 private byte[] getPatchedByteCode(String name) throws ClassNotFoundException {
104 try {
105 byte[] bytecode = getByteCode();
106 String fname = name.replace(".", File.separator);
107 byte[] replaceBytes = fname.getBytes(encoding);
108 for (int offset : offsets) {
109 for (int i = 0; i < replaceBytes.length; ++i) {
110 bytecode[offset + i] = replaceBytes[i];
111 }
112 }
166 break;
167 }
168 i++;
169 }
170 if (i == bytecode.length) {
171 break;
172 }
173 offsets.add(new Integer(i));
174 i++;
175 }
176 } catch (UnsupportedEncodingException e) {
177 throw new RuntimeException(e);
178 }
179 this.offsets = new int[offsets.size()];
180 for (int i = 0; i < offsets.size(); ++i) {
181 this.offsets[i] = offsets.get(i).intValue();
182 }
183 }
184 }
185
186 static final String DEFAULT_CLASSNAME = TemplateClass.class.getName();
187 static final String PREFIX = "Class";
188
189 private final String[] classPath;
190 private byte[] bytecode;
191 private int[] offsets;
192 private final String encoding = "UTF8";
193 private final String templateClassName;
194 private final byte[] templateClassNameBytes;
195 }
|
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 package jdk.test.lib.classloader;
24
25 import java.io.*;
26 import java.util.*;
27
28 /**
29 * Classloader that generates classes on the fly.
30 *
31 * This classloader can load classes with name starting with 'Class'. It will
32 * use TemplateClass as template and will replace class name in the bytecode of
33 * template class. It can be used for example to detect memory leaks in class
34 * loading or to quickly fill Metaspace.
35 */
36 class TemplateClass {
37 }
38
39 public class GeneratingClassLoader extends ClassLoader {
40
41 public synchronized Class loadClass(String name) throws ClassNotFoundException {
42 return loadClass(name, false);
43 }
44
45 public synchronized Class loadClass(String name, boolean resolve)
46 throws ClassNotFoundException {
47 Class c = findLoadedClass(name);
48 if (c != null) {
49 return c;
50 }
51 if (!name.startsWith(PREFIX)) {
52 return super.loadClass(name, resolve);
53 }
54 if (name.length() != templateClassName.length()) {
55 throw new ClassNotFoundException("Only can load classes with name.length() = " + getNameLength() + " got: '" + name + "' length: " + name.length());
56 }
57 byte[] bytecode = getPatchedByteCode(name);
58 c = defineClass(name, bytecode, 0, bytecode.length);
59 if (resolve) {
60 resolveClass(c);
61 }
62 return c;
63 }
64
65 /**
66 * Create generating class loader that will use class file for given class
67 * from classpath as template.
68 */
69 public GeneratingClassLoader(String templateClassName) {
70 this.templateClassName = templateClassName;
71 classPath = System.getProperty("java.class.path").split(File.pathSeparator);
72 try {
73 templateClassNameBytes = templateClassName.getBytes(encoding);
74 } catch (UnsupportedEncodingException e) {
75 throw new RuntimeException(e);
76 }
77 }
78
79 /**
80 * Create generating class loader that will use class file for
81 * nsk.share.classload.TemplateClass as template.
82 */
83 public GeneratingClassLoader() {
84 this(TemplateClass.class.getName());
85 }
86
87 public int getNameLength() {
88 return templateClassName.length();
89 }
90
91 String getPrefix() {
92 return PREFIX;
93 }
94
95 public String getClassName(int number) {
96 StringBuffer sb = new StringBuffer();
97 sb.append(PREFIX);
98 sb.append(number);
99 int n = templateClassName.length() - sb.length();
100 for (int i = 0; i < n; ++i) {
101 sb.append("_");
102 }
103 return sb.toString();
104 }
105
106 private byte[] getPatchedByteCode(String name) throws ClassNotFoundException {
107 try {
108 byte[] bytecode = getByteCode();
109 String fname = name.replace(".", File.separator);
110 byte[] replaceBytes = fname.getBytes(encoding);
111 for (int offset : offsets) {
112 for (int i = 0; i < replaceBytes.length; ++i) {
113 bytecode[offset + i] = replaceBytes[i];
114 }
115 }
169 break;
170 }
171 i++;
172 }
173 if (i == bytecode.length) {
174 break;
175 }
176 offsets.add(new Integer(i));
177 i++;
178 }
179 } catch (UnsupportedEncodingException e) {
180 throw new RuntimeException(e);
181 }
182 this.offsets = new int[offsets.size()];
183 for (int i = 0; i < offsets.size(); ++i) {
184 this.offsets[i] = offsets.get(i).intValue();
185 }
186 }
187 }
188
189 public static final String DEFAULT_CLASSNAME = TemplateClass.class.getName();
190 static final String PREFIX = "Class";
191
192 private final String[] classPath;
193 private byte[] bytecode;
194 private int[] offsets;
195 private final String encoding = "UTF8";
196 private final String templateClassName;
197 private final byte[] templateClassNameBytes;
198 }
|