提交 525b9fa8 编写于 作者: C ctornqvi

8009576: Test returns ClassNotFoundException

Summary: Small classpath fix and move tests into open
Reviewed-by: mgerdin, zgu
上级 14343bb0
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @library /runtime/testlibrary
* @build GeneratedClassLoader
* @run main/othervm/timeout=200 FragmentMetaspace
*/
import java.io.IOException;
/**
* Test that tries to fragment the native memory used by class loaders.
* This test creates class loaders that load classes of increasing size for every
* iteration. By increasing the size of the class meta data needed for every iteration
* we stress the subsystem for allocating native memory for meta data.
*/
public class FragmentMetaspace {
public static void main(String... args) {
runGrowing(Long.valueOf(System.getProperty("time", "80000")));
// try to clean up and unload classes to decrease
// class verification time in debug vm
System.gc();
}
private static void runGrowing(long time) {
long startTime = System.currentTimeMillis();
for (int i = 0; System.currentTimeMillis() < startTime + time; ++i) {
try {
GeneratedClassLoader gcl = new GeneratedClassLoader();
Class<?> c = gcl.getGeneratedClasses(i, 100)[0];
c.newInstance();
c = null;
gcl = null;
} catch (IOException|InstantiationException|IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @library /runtime/testlibrary
* @library classes
* @build test.Empty ClassUnloadCommon
* @run main/othervm/timeout=200 FragmentMetaspaceSimple
*/
import java.util.ArrayList;
/**
* Test that tries to fragment the native memory used by class loaders.
* Keeps every other class loader alive in order to fragment the memory space
* used to store classes and meta data. Since the memory is probably allocated in
* chunks per class loader this will cause a lot of fragmentation if not handled
* properly since every other chunk will be unused.
*/
public class FragmentMetaspaceSimple {
public static void main(String... args) {
runSimple(Long.valueOf(System.getProperty("time", "80000")));
System.gc();
}
private static void runSimple(long time) {
long startTime = System.currentTimeMillis();
ArrayList<ClassLoader> cls = new ArrayList<>();
for (int i = 0; System.currentTimeMillis() < startTime + time; ++i) {
ClassLoader ldr = ClassUnloadCommon.newClassLoader();
if (i % 1000 == 0) {
cls.clear();
}
// only keep every other class loader alive
if (i % 2 == 1) {
cls.add(ldr);
}
Class<?> c = null;
try {
c = ldr.loadClass("test.Empty");
} catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
c = null;
}
cls = null;
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package test;
public class Empty {
public String toString() { return "nothing"; }
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
/**
* A class loader that generates new classes.
* The generated classes are made by first emitting java sources with nested
* static classes, these are then compiled and the class files are read back.
* Some efforts are made to make the class instances unique and of not insignificant
* size.
*/
public class GeneratedClassLoader extends ClassLoader {
/**
* Holds a pair of class bytecodes and class name (for use with defineClass).
*/
private static class GeneratedClass {
public byte[] bytes;
public String name;
public GeneratedClass(byte[] bytes, String name) {
this.bytes = bytes; this.name = name;
}
}
/**
* Used to uniquely name every class generated.
*/
private static int count = 0;
/**
* Used to enable/disable keeping the class files and java sources for
* the generated classes.
*/
private static boolean deleteFiles = Boolean.parseBoolean(
System.getProperty("GeneratedClassLoader.deleteFiles", "true"));
private static String bigstr =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
+ "In facilisis scelerisque vehicula. Donec congue nisi a "
+ "leo posuere placerat lobortis felis ultrices. Pellentesque "
+ "habitant morbi tristique senectus et netus et malesuada "
+ "fames ac turpis egestas. Nam tristique velit at felis "
+ "iaculis at tempor sem vestibulum. Sed adipiscing lectus "
+ "non mi molestie sagittis. Morbi eu purus urna. Nam tempor "
+ "tristique massa eget semper. Mauris cursus, nulla et ornare "
+ "vehicula, leo dolor scelerisque metus, sit amet rutrum erat "
+ "sapien quis dui. Nullam eleifend risus et velit accumsan sed "
+ "suscipit felis pulvinar. Nullam faucibus suscipit gravida. "
+ "Pellentesque habitant morbi tristique senectus et netus et "
+ "malesuada fames ac turpis egestas. Nullam ut massa augue, "
+ "nec viverra mauris.";
private static int getNextCount() {
return count++;
}
////// end statics
private JavaCompiler javac;
private String nameBase;
public GeneratedClassLoader() {
javac = ToolProvider.getSystemJavaCompiler();
nameBase = "TestSimpleClass";
}
private long getBigValue(int which) {
// > 65536 is too large to encode in the bytecode
// so this will force us to emit a constant pool entry for this int
return (long)which + 65537;
}
private String getBigString(int which) {
return bigstr + which;
}
private String getClassName(int count) {
return nameBase + count;
}
private String generateSource(int count, int sizeFactor, int numClasses) {
StringBuilder sb = new StringBuilder();
sb.append("public class ").append(getClassName(count)).append("{\n");
for (int j = 0; j < numClasses; ++j) {
sb.append("public static class ")
.append("Class")
.append(j)
.append("{\n");
for (int i = 0; i < sizeFactor; ++i) {
int value = i;
sb.append("private long field")
.append(i).append(" = ")
.append(getBigValue(value++))
.append(";\n");
sb.append("public long method")
.append(i)
.append("() {\n");
sb.append("return ")
.append(getBigValue(value++))
.append(";");
sb.append("}\n");
sb.append("private String str").append(i)
.append(" = \"")
.append(getBigString(i))
.append("\";");
}
sb.append("\n}");
}
sb.append("\n}");
return sb.toString();
}
private GeneratedClass[] getGeneratedClass(int sizeFactor, int numClasses) throws IOException {
int uniqueCount = getNextCount();
String src = generateSource(uniqueCount, sizeFactor, numClasses);
String className = getClassName(uniqueCount);
File file = new File(className + ".java");
try (PrintWriter pw = new PrintWriter(new FileWriter(file))) {
pw.append(src);
pw.flush();
}
int exitcode = javac.run(null, null, null, file.getCanonicalPath());
if (exitcode != 0) {
throw new RuntimeException("javac failure when compiling: " +
file.getCanonicalPath());
} else {
if (deleteFiles) {
file.delete();
}
}
GeneratedClass[] gc = new GeneratedClass[numClasses];
for (int i = 0; i < numClasses; ++i) {
String name = className + "$" + "Class" + i;
File classFile = new File(name + ".class");
byte[] bytes;
try (DataInputStream dis = new DataInputStream(new FileInputStream(classFile))) {
bytes = new byte[dis.available()];
dis.readFully(bytes);
}
if (deleteFiles) {
classFile.delete();
}
gc[i] = new GeneratedClass(bytes, name);
}
if (deleteFiles) {
new File(className + ".class").delete();
}
return gc;
}
/**
* Generate a single class, compile it and load it.
* @param sizeFactor Fuzzy measure of how large the class should be.
* @return the Class instance.
* @throws IOException
*/
public Class<?> generateClass(int sizeFactor) throws IOException {
return getGeneratedClasses(sizeFactor, 1)[0];
}
/**
* Generate several classes, compile and load them.
* @param sizeFactor Fuzzy measure of how large each class should be.
* @param numClasses The number of classes to create
* @return an array of the Class instances.
* @throws IOException
*/
public Class<?>[] getGeneratedClasses(int sizeFactor, int numClasses) throws IOException {
GeneratedClass[] gc = getGeneratedClass(sizeFactor, numClasses);
Class<?>[] classes = new Class[numClasses];
for (int i = 0; i < numClasses; ++i) {
classes[i] = defineClass(gc[i].name, gc[i].bytes, 0 , gc[i].bytes.length);
}
return classes;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册