8203820: [TESTBUG] vmTestbase/metaspace/staticReferences/StaticReferences.java timed out

Moved InMemoryJavaCompiler out of loops or reduced loops with InMemoryJavaCompiler

Reviewed-by: vromero, jiangli
This commit is contained in:
Coleen Phillimore 2018-07-20 18:03:23 -04:00
parent 61ea10862e
commit a95225aabc
3 changed files with 82 additions and 87 deletions

View File

@ -67,7 +67,7 @@ import vm.share.gc.TriggerUnloadingWithWhiteBox;
/** /**
* Test checks that static fields will be initialized in new loaded class. Test performs in loop the following routine: * Test checks that static fields will be initialized in new loaded class. Test performs in loop the following routine:
* 1.) Load class either by regular classloader or by Unsafe.defineAnonymousClass. * 1.) Load class either by regular classloader or by Unsafe.defineAnonymousClass.
* 2.) Trigger unloading. Class must be alive. Next step will check that static fields would not lost. * 2.) Trigger unloading. Class must be alive. Next step will check that static fields were not lost.
* 3.) Change static fields. * 3.) Change static fields.
* 4.) Unload class. * 4.) Unload class.
* 5.) Load class again as in step 1. * 5.) Load class again as in step 1.
@ -82,7 +82,7 @@ public class StaticReferences extends GCTestBase {
private static String[] args; private static String[] args;
private static final int LIMIT = 100; private static final int LIMIT = 20;
private List<Object> keepAlive = new LinkedList<Object>(); private List<Object> keepAlive = new LinkedList<Object>();
@ -103,7 +103,7 @@ public class StaticReferences extends GCTestBase {
@Override @Override
public void run() { public void run() {
random = new Random(runParams.getSeed()); random = new Random(runParams.getSeed());
ExecutionController stresser = new Stresser(args); ExecutionController stresser = new Stresser(args);
stresser.start(1); stresser.start(1);
@ -116,7 +116,7 @@ public class StaticReferences extends GCTestBase {
return; return;
} }
for (int j = 0; j < fieldQuantities.length; j++) { for (int j = 0; j < fieldQuantities.length; j++) {
fieldQuantities[j] = 1 + random.nextInt(2000); fieldQuantities[j] = 1 + random.nextInt(20);
} }
bytecodeList.add(generateAndCompile(fieldQuantities)); bytecodeList.add(generateAndCompile(fieldQuantities));
} }
@ -209,9 +209,9 @@ public class StaticReferences extends GCTestBase {
} }
} }
private byte[] generateAndCompile(int[] filedQuantities) { private byte[] generateAndCompile(int[] fieldQuantities) {
Map<String, CharSequence> sources = new HashMap<String, CharSequence>(); Map<String, CharSequence> sources = new HashMap<String, CharSequence>();
sources.put("A", generateSource(filedQuantities)); sources.put("A", generateSource(fieldQuantities));
return InMemoryJavaCompiler.compile(sources).values().iterator().next(); return InMemoryJavaCompiler.compile(sources).values().iterator().next();
} }

View File

@ -29,7 +29,7 @@
* *
* @library /vmTestbase /test/lib * @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . . * @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm metaspace.stressDictionary.StressDictionary * @run main/othervm metaspace.stressDictionary.StressDictionary -stressTime 30
*/ */
package metaspace.stressDictionary; package metaspace.stressDictionary;
@ -57,15 +57,16 @@ import vm.share.InMemoryJavaCompiler;
*/ */
public class StressDictionary extends GCTestBase { public class StressDictionary extends GCTestBase {
private static byte[] bytecode;
private class FillingDictionaryWorker implements Callable<Object> { private class FillingDictionaryWorker implements Callable<Object> {
@Override @Override
public Object call() throws Exception { public Object call() throws Exception {
while (stresser.continueExecution()) { while (stresser.continueExecution()) {
try { try {
byte[] bytecode = generateAndCompile(); byte[] badBytecode = bytecode.clone();
bytecode[random.nextInt(bytecode.length)] = (byte) 42; badBytecode[random.nextInt(badBytecode.length)] = (byte) 42;
classloader.define(bytecode); classloader.define(badBytecode);
changeClassloaderIfRequired();
} catch (Throwable e) { } catch (Throwable e) {
// We can get ClassFormatError, ClassNotFoundException or anything else here // We can get ClassFormatError, ClassNotFoundException or anything else here
} }
@ -78,10 +79,8 @@ public class StressDictionary extends GCTestBase {
@Override @Override
public Object call() throws Exception { public Object call() throws Exception {
while (stresser.continueExecution()) { while (stresser.continueExecution()) {
byte[] bytecode = generateAndCompile();
Class<?> c = classloader.define(bytecode); Class<?> c = classloader.define(bytecode);
testClass(c); testClass(c);
changeClassloaderIfRequired();
} }
return null; return null;
} }
@ -89,8 +88,6 @@ public class StressDictionary extends GCTestBase {
private static String[] args; private static String[] args;
private static final int DROP_CLASSLOADER_LIMIT = 50000;
private static final String methodName = "myMethod"; private static final String methodName = "myMethod";
private static final int NUMBER_OF_CORRUPTING_THREADS = 10; private static final int NUMBER_OF_CORRUPTING_THREADS = 10;
@ -116,6 +113,8 @@ public class StressDictionary extends GCTestBase {
random = new Random(runParams.getSeed()); random = new Random(runParams.getSeed());
stresser = new Stresser(args); stresser = new Stresser(args);
stresser.start(1); stresser.start(1);
// Generate some bytecodes.
bytecode = generateAndCompile();
List<Callable<Object>> tasks = new LinkedList<Callable<Object>>(); List<Callable<Object>> tasks = new LinkedList<Callable<Object>>();
for (int i = 0; i < NUMBER_OF_CORRUPTING_THREADS; i++) { for (int i = 0; i < NUMBER_OF_CORRUPTING_THREADS; i++) {
tasks.add(this.new FillingDictionaryWorker()); tasks.add(this.new FillingDictionaryWorker());
@ -131,13 +130,6 @@ public class StressDictionary extends GCTestBase {
} }
} }
private void changeClassloaderIfRequired() {
if (ManagementFactory.getClassLoadingMXBean().getLoadedClassCount() > DROP_CLASSLOADER_LIMIT) {
ClassloaderUnderTest newOne = new ClassloaderUnderTest();
classloader = newOne;
}
}
private byte[] generateAndCompile() { private byte[] generateAndCompile() {
Map<String, CharSequence> sources = new HashMap<String, CharSequence>(); Map<String, CharSequence> sources = new HashMap<String, CharSequence>();
String className = "MyClass" + classesCounter.incrementAndGet(); String className = "MyClass" + classesCounter.incrementAndGet();

View File

@ -61,7 +61,10 @@ public class StressRedefine extends GCTestBase {
private static ExecutionController stresser; private static ExecutionController stresser;
private static String[] args; private static String[] args;
// This is random generator used for generating seeds for other Randoms. Setting seed from command line sets seed for this random. private static byte[] bytecode;
// This is random generator used for generating seeds for other Randoms. Setting seed
// from command line sets seed for this random.
static Random seedGenerator; static Random seedGenerator;
static { static {
@ -82,47 +85,53 @@ public class StressRedefine extends GCTestBase {
Tests.runTest(new StressRedefine(), args); Tests.runTest(new StressRedefine(), args);
} }
@Override @Override
public void run() { public void run() {
seedGenerator = new Random(runParams.getSeed()); seedGenerator = new Random(runParams.getSeed());
GenerateSourceHelper.setRandom(new Random(seedGenerator.nextLong())); GenerateSourceHelper.setRandom(new Random(seedGenerator.nextLong()));
stresser = new Stresser(args); stresser = new Stresser(args);
for (int i = 0; i < args.length; i++ ) { for (int i = 0; i < args.length; i++ ) {
if ("-staticMethodCallersNumber".equals(args[i])) { if ("-staticMethodCallersNumber".equals(args[i])) {
staticMethodCallersNumber = Integer.parseInt(args[i + 1]); staticMethodCallersNumber = Integer.parseInt(args[i + 1]);
} else if ("-nonstaticMethodCallersNumber".equals(args[i])) { } else if ("-nonstaticMethodCallersNumber".equals(args[i])) {
nonstaticMethodCallersNumber = Integer.parseInt(args[i + 1]); nonstaticMethodCallersNumber = Integer.parseInt(args[i + 1]);
} else if ("-redefiningThreadsNumber".equals(args[i])) { } else if ("-redefiningThreadsNumber".equals(args[i])) {
redefiningThreadsNumber = Integer.parseInt(args[i + 1]); redefiningThreadsNumber = Integer.parseInt(args[i + 1]);
} else if ("-corruptingBytecodeProbability".equals(args[i])) { } else if ("-corruptingBytecodeProbability".equals(args[i])) {
corruptingBytecodeProbability = Double.parseDouble(args[i + 1]); corruptingBytecodeProbability = Double.parseDouble(args[i + 1]);
} }
} }
//Dynamic attach if required //Dynamic attach if required
nsk.share.jvmti.JVMTITest.commonInit(args); nsk.share.jvmti.JVMTITest.commonInit(args);
new StressRedefine().runIt(); new StressRedefine().runIt();
}
private static void runMethod(Random random, String name) {
while (stresser.continueExecution()) {
try {
// Just for fun we transfer parameters to method
Object res = myClass.getMethod(name, double.class, int.class, Object.class)
.invoke(null, random.nextDouble(), random.nextInt(), new Object());
} catch (IllegalArgumentException | InvocationTargetException
| IllegalAccessException | NoSuchMethodException e) {
// It's okay to get exception here since we are corrupting bytecode and can't expect
// class to work properly.
System.out.println("Got expected exception: " + e.toString());
}
} }
}
private static class StaticMethodCaller implements Runnable { private static class StaticMethodCaller implements Runnable {
private Random random; private Random random;
public StaticMethodCaller() {random = new Random(seedGenerator.nextLong());} public StaticMethodCaller() {random = new Random(seedGenerator.nextLong());}
@Override @Override
public void run() { public void run() {
while (stresser.continueExecution()) { runMethod(random, GenerateSourceHelper.STATIC_METHOD_NAME);
try { }
Object res = myClass.getMethod(GenerateSourceHelper.STATIC_METHOD_NAME, double.class, int.class, Object.class).invoke(
null, random.nextDouble(), random.nextInt(), new Object()); // Just for fun we transfer parameters to method
} catch (IllegalArgumentException | InvocationTargetException
| IllegalAccessException | NoSuchMethodException e) {
//It's okay to get exception here since we are corrupting bytecode and can't expect class to work properly.
System.out.println("Got expected exception: " + e.toString());
}
}
}
} }
private static class NonstaticMethodCaller implements Runnable { private static class NonstaticMethodCaller implements Runnable {
@ -130,59 +139,54 @@ public class StressRedefine extends GCTestBase {
public NonstaticMethodCaller() {random = new Random(seedGenerator.nextLong());} public NonstaticMethodCaller() {random = new Random(seedGenerator.nextLong());}
@Override @Override
public void run() { public void run() {
while (stresser.continueExecution()) { runMethod(random, GenerateSourceHelper.NONSTATIC_METHOD_NAME);
try { }
Object res = myClass.getMethod(GenerateSourceHelper.NONSTATIC_METHOD_NAME, double.class, int.class, Object.class).
invoke(myClass.newInstance(), random.nextDouble(), random.nextInt(), new Object()); // Just for fun we transfer parameters to method
} catch (IllegalArgumentException | InvocationTargetException | NoSuchMethodException | InstantiationException | IllegalAccessException e) {
//It's okay to get exception here since we are corrupting bytecode and can't expect class to work properly.
System.out.println("Got expected exception: " + e.toString());
}
}
}
} }
private static class Worker implements Runnable { private static class Worker implements Runnable {
private Random random; private Random random;
public Worker() {random = new Random(seedGenerator.nextLong());} public Worker() {random = new Random(seedGenerator.nextLong());}
@Override @Override
public void run() { public void run() {
while (stresser.continueExecution()) { while (stresser.continueExecution()) {
byte[] bytecode = generateAndCompile(); byte[] badBytecode = bytecode.clone();
if (random.nextDouble() < corruptingBytecodeProbability) { if (random.nextDouble() < corruptingBytecodeProbability) {
bytecode[random.nextInt(bytecode.length)] = 42; badBytecode[random.nextInt(bytecode.length)] = 42;
}
makeRedefinition(2, myClass, bytecode);
}
} }
makeRedefinition(2, myClass, badBytecode);
}
}
} }
private void runIt() { private void runIt() {
myClass = new DefiningClassLoader().defineClass(generateAndCompile()); myClass = new DefiningClassLoader().defineClass(generateAndCompile());
stresser.start(0); stresser.start(0);
// Generate some bytecode.
bytecode = generateAndCompile();
List<Thread> threads = new LinkedList<Thread>(); List<Thread> threads = new LinkedList<Thread>();
for (int i = 0; i < staticMethodCallersNumber; i++) { for (int i = 0; i < staticMethodCallersNumber; i++) {
threads.add(new Thread(new StaticMethodCaller())); threads.add(new Thread(new StaticMethodCaller()));
} }
for (int i = 0; i < nonstaticMethodCallersNumber; i++) { for (int i = 0; i < nonstaticMethodCallersNumber; i++) {
threads.add(new Thread(new NonstaticMethodCaller())); threads.add(new Thread(new NonstaticMethodCaller()));
} }
for (int i = 0; i < redefiningThreadsNumber; i++) { for (int i = 0; i < redefiningThreadsNumber; i++) {
threads.add(new Thread(new Worker())); threads.add(new Thread(new Worker()));
} }
for (Thread thread : threads) { for (Thread thread : threads) {
thread.start(); thread.start();
} }
for (Thread thread : threads) { for (Thread thread : threads) {
try { try {
thread.join(); thread.join();
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new TestFailure("Thread " + Thread.currentThread() + " was interrupted:", e); throw new TestFailure("Thread " + Thread.currentThread() + " was interrupted:", e);
} }
} }
} }
@ -192,15 +196,14 @@ public class StressRedefine extends GCTestBase {
return InMemoryJavaCompiler.compile(sources).values().iterator().next(); return InMemoryJavaCompiler.compile(sources).values().iterator().next();
} }
// Auxiliary classloader. Used only once at the beginning. // Auxiliary classloader. Used only once at the beginning.
private static class DefiningClassLoader extends URLClassLoader { private static class DefiningClassLoader extends URLClassLoader {
public DefiningClassLoader() { public DefiningClassLoader() {
super(new URL[0]); super(new URL[0]);
}
Class<?> defineClass(byte[] bytecode) {
return defineClass(null, bytecode, 0, bytecode.length);
}
} }
Class<?> defineClass(byte[] bytecode) {
return defineClass(null, bytecode, 0, bytecode.length);
}
}
} }