8062904: TEST_BUG: Tests java/lang/invoke/LFCaching fail when run with -Xcomp option
Reviewed-by: vlivanov
diff --git a/test/java/lang/invoke/LFCaching/LFCachingTestCase.java b/test/java/lang/invoke/LFCaching/LFCachingTestCase.java
index 50a57e4..b5f99bd 100644
--- a/test/java/lang/invoke/LFCaching/LFCachingTestCase.java
+++ b/test/java/lang/invoke/LFCaching/LFCachingTestCase.java
@@ -77,7 +77,7 @@
}
} catch (IllegalAccessException | IllegalArgumentException |
SecurityException | InvocationTargetException ex) {
- throw new Error("Unexpected exception: ", ex);
+ throw new Error("Unexpected exception", ex);
}
}
}
diff --git a/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java b/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java
index a60d460..347fabb 100644
--- a/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java
+++ b/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java
@@ -59,10 +59,10 @@
super(testMethod);
}
- PhantomReference ph;
- ReferenceQueue rq = new ReferenceQueue();
- MethodType mtype;
- Map<String, Object> data;
+ PhantomReference ph;
+ ReferenceQueue rq = new ReferenceQueue();
+ MethodType mtype;
+ Map<String, Object> data;
@Override
public void doTest() {
@@ -73,7 +73,7 @@
try {
adapter = testCase.getTestCaseMH(data, TestMethods.Kind.ONE);
} catch (NoSuchMethodException ex) {
- throw new Error("Unexpected exception: ", ex);
+ throw new Error("Unexpected exception", ex);
}
mtype = adapter.type();
Object lambdaForm = INTERNAL_FORM.invoke(adapter);
@@ -94,12 +94,12 @@
collectLambdaForm();
} catch (IllegalAccessException | IllegalArgumentException |
InvocationTargetException ex) {
- throw new Error("Unexpected exception: ", ex);
+ throw new Error("Unexpected exception", ex);
}
}
private void collectLambdaForm() throws IllegalAccessException {
- // Usually, 2 System.GCs are necessary to enqueue a SoftReference.
+ // Usually, 2 System.GCs are necessary to enqueue a SoftReference.
System.gc();
System.gc();
@@ -129,7 +129,7 @@
};
}
- private void dumpTestData() {
+ private void dumpTestData() {
System.err.println("Test case: " + getTestMethod());
for (String s : data.keySet()) {
System.err.printf("\t%20s => %s\n", s, data.get(s));
diff --git a/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java b/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java
index 35c2f97..05d378b 100644
--- a/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java
+++ b/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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
@@ -35,18 +35,23 @@
*/
import java.lang.invoke.MethodHandle;
+import java.util.Collections;
import java.util.EnumSet;
+import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
+import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor;
/**
* Multiple threaded lambda forms caching test class.
*/
public final class LFMultiThreadCachingTest extends LFCachingTestCase {
+
private static final TestMethods.Kind[] KINDS;
+
static {
EnumSet<TestMethods.Kind> set = EnumSet.complementOf(EnumSet.of(TestMethods.Kind.EXCEPT));
KINDS = set.toArray(new TestMethods.Kind[set.size()]);
@@ -72,21 +77,55 @@
ConcurrentLinkedQueue<MethodHandle> adapters = new ConcurrentLinkedQueue<>();
CyclicBarrier begin = new CyclicBarrier(CORES);
CountDownLatch end = new CountDownLatch(CORES);
+ final Map<Thread, Throwable> threadUncaughtExceptions
+ = Collections.synchronizedMap(new HashMap<Thread, Throwable>(CORES));
+ Thread.UncaughtExceptionHandler exHandler = (t, e) -> {
+ threadUncaughtExceptions.put(t, e);
+ };
for (int i = 0; i < CORES; ++i) {
TestMethods.Kind kind = KINDS[i % KINDS.length];
- new Thread(() -> {
+ Thread t = new Thread(() -> {
try {
begin.await();
adapters.add(getTestMethod().getTestCaseMH(data, kind));
- } catch (InterruptedException | BrokenBarrierException | IllegalAccessException | NoSuchMethodException ex) {
- throw new Error("Unexpected exception: ", ex);
+ } catch (InterruptedException | BrokenBarrierException
+ | IllegalAccessException | NoSuchMethodException ex) {
+ throw new Error("Unexpected exception", ex);
} finally {
end.countDown();
}
- }).start();
+ });
+ t.setUncaughtExceptionHandler(exHandler);
+ t.start();
}
try {
end.await();
+ boolean vmeThrown = false;
+ boolean nonVmeThrown = false;
+ Throwable vme = null;
+ for (Map.Entry<Thread,
+ Throwable> entry : threadUncaughtExceptions.entrySet()) {
+ Thread t = entry.getKey();
+ Throwable e = entry.getValue();
+ System.err.printf("%nA thread with name \"%s\" of %d threads"
+ + " has thrown exception:%n", t.getName(), CORES);
+ e.printStackTrace();
+ if (CodeCacheOverflowProcessor.isThrowableCausedByVME(e)) {
+ vmeThrown = true;
+ vme = e;
+ } else {
+ nonVmeThrown = true;
+ }
+ if (nonVmeThrown) {
+ throw new Error("One ore more threads have"
+ + " thrown unexpected exceptions. See log.");
+ }
+ if (vmeThrown) {
+ throw new Error("One ore more threads have"
+ + " thrown VirtualMachineError caused by"
+ + " code cache overflow. See log.", vme);
+ }
+ }
} catch (InterruptedException ex) {
throw new Error("Unexpected exception: ", ex);
}
diff --git a/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java b/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java
index 6a44e44..3d468a4 100644
--- a/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java
+++ b/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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
@@ -62,7 +62,7 @@
adapter1 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE);
adapter2 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.TWO);
} catch (NoSuchMethodException | IllegalAccessException ex) {
- throw new Error("Unexpected exception: ", ex);
+ throw new Error("Unexpected exception", ex);
}
checkLFCaching(adapter1, adapter2);
}
diff --git a/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java b/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java
index 5d037ca..f945883 100644
--- a/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java
+++ b/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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
@@ -22,8 +22,7 @@
*/
import com.oracle.testlibrary.jsr292.Helper;
-import com.sun.management.HotSpotDiagnosticMXBean;
-
+import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor;
import java.lang.invoke.MethodHandle;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
@@ -45,8 +44,6 @@
*/
public abstract class LambdaFormTestCase {
- private static final double ITERATIONS_TO_CODE_CACHE_SIZE_RATIO
- = 45 / (128.0 * 1024 * 1024);
private static final long TIMEOUT = Helper.IS_THOROUGH ? 0L : (long) (Utils.adjustTimeout(Utils.DEFAULT_TEST_TIMEOUT) * 0.9);
/**
@@ -73,23 +70,89 @@
REF_FIELD = Reference.class.getDeclaredField("referent");
REF_FIELD.setAccessible(true);
} catch (Exception ex) {
- throw new Error("Unexpected exception: ", ex);
+ throw new Error("Unexpected exception", ex);
}
gcInfo = ManagementFactory.getGarbageCollectorMXBeans();
- if (gcInfo.size() == 0) {
+ if (gcInfo.size() == 0) {
throw new Error("No GarbageCollectorMXBeans found.");
}
}
private final TestMethods testMethod;
- private static long totalIterations = 0L;
- private static long doneIterations = 0L;
- private static boolean passed = true;
- private static int testCounter = 0;
- private static int failCounter = 0;
private long gcCountAtStart;
+ private static class TestRun {
+
+ final Function<TestMethods, LambdaFormTestCase> ctor;
+ final Collection<TestMethods> testMethods;
+ final long totalIterations;
+ long doneIterations;
+ long testCounter;
+ long failCounter;
+ boolean passed;
+
+ TestRun(Function<TestMethods, LambdaFormTestCase> ctor, Collection<TestMethods> testMethods) {
+ this.ctor = ctor;
+ this.testMethods = testMethods;
+ long testCaseNum = testMethods.size();
+ long iterations = Math.max(1, Helper.TEST_LIMIT / testCaseNum);
+ System.out.printf("Number of iterations according to -DtestLimit is %d (%d cases)%n",
+ iterations, iterations * testCaseNum);
+ System.out.printf("Number of iterations is set to %d (%d cases)%n",
+ iterations, iterations * testCaseNum);
+ System.out.flush();
+ totalIterations = iterations;
+ doneIterations = 0L;
+ testCounter = 0L;
+ failCounter = 0L;
+ passed = true;
+ }
+
+ Boolean doIteration() {
+ if (doneIterations >= totalIterations) {
+ return false;
+ }
+ System.err.println(String.format("Iteration %d:", doneIterations));
+ for (TestMethods testMethod : testMethods) {
+ LambdaFormTestCase testCase = ctor.apply(testMethod);
+ try {
+ System.err.printf("Tested LF caching feature"
+ + " with MethodHandles.%s method.%n",
+ testCase.getTestMethod().name);
+ Throwable t = CodeCacheOverflowProcessor
+ .runMHTest(testCase::doTest);
+ if (t != null) {
+ return false;
+ }
+ System.err.println("PASSED");
+ } catch (OutOfMemoryError oome) {
+ // Don't swallow OOME so a heap dump can be created.
+ System.err.println("FAILED");
+ throw oome;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ System.err.printf("FAILED. Caused by %s%n", t.getMessage());
+ passed = false;
+ failCounter++;
+ }
+ testCounter++;
+ }
+ doneIterations++;
+ return true;
+ }
+
+ void checkPassed() {
+ if (!passed) {
+ throw new Error(String.format("%d of %d test cases FAILED! %n"
+ + "Rerun the test with the same \"-Dseed=\" option as in the log file!",
+ failCounter, testCounter));
+ } else {
+ System.err.printf("All %d test cases PASSED!%n", testCounter);
+ }
+ }
+ }
+
/**
* Test case constructor. Generates test cases with random method types for
* given methods form {@code j.l.i.MethodHandles} class.
@@ -123,65 +186,15 @@
* @param testMethods list of test methods
*/
public static void runTests(Function<TestMethods, LambdaFormTestCase> ctor, Collection<TestMethods> testMethods) {
- long testCaseNum = testMethods.size();
- totalIterations = Math.max(1, Helper.TEST_LIMIT / testCaseNum);
- System.out.printf("Number of iterations according to -DtestLimit is %d (%d cases)%n",
- totalIterations, totalIterations * testCaseNum);
- HotSpotDiagnosticMXBean hsDiagBean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
- long codeCacheSize = Long.parseLong(
- hsDiagBean.getVMOption("ReservedCodeCacheSize").getValue());
- System.out.printf("Code Cache Size is %d bytes%n", codeCacheSize);
- long iterationsByCodeCacheSize = (long) (codeCacheSize
- * ITERATIONS_TO_CODE_CACHE_SIZE_RATIO);
- System.out.printf("Number of iterations limited by code cache size is %d (%d cases)%n",
- iterationsByCodeCacheSize, iterationsByCodeCacheSize * testCaseNum);
- if (totalIterations > iterationsByCodeCacheSize) {
- totalIterations = iterationsByCodeCacheSize;
- }
- System.out.printf("Number of iterations is set to %d (%d cases)%n",
- totalIterations, totalIterations * testCaseNum);
- System.out.flush();
- TimeLimitedRunner runner = new TimeLimitedRunner(TIMEOUT, 4.0d,
- () -> {
- if (doneIterations >= totalIterations) {
- return false;
- }
- System.err.println(String.format("Iteration %d:", doneIterations));
- for (TestMethods testMethod : testMethods) {
- LambdaFormTestCase testCase = ctor.apply(testMethod);
- try {
- System.err.printf("Tested LF caching feature with MethodHandles.%s method.%n",
- testCase.getTestMethod().name);
- testCase.doTest();
- System.err.println("PASSED");
- } catch (OutOfMemoryError e) {
- // Don't swallow OOME so a heap dump can be created.
- System.err.println("FAILED");
- throw e;
- } catch (Throwable t) {
- t.printStackTrace();
- System.err.println("FAILED");
- passed = false;
- failCounter++;
- }
- testCounter++;
- }
- doneIterations++;
- return true;
- });
+ LambdaFormTestCase.TestRun run
+ = new LambdaFormTestCase.TestRun(ctor, testMethods);
+ TimeLimitedRunner runner = new TimeLimitedRunner(TIMEOUT, 4.0d, run::doIteration);
try {
runner.call();
- } catch (Throwable t) {
- t.printStackTrace();
+ } catch (Exception ex) {
System.err.println("FAILED");
- throw new Error("Unexpected error!");
+ throw new Error("Unexpected error!", ex);
}
- if (!passed) {
- throw new Error(String.format("%d of %d test cases FAILED! %n"
- + "Rerun the test with the same \"-Dseed=\" option as in the log file!",
- failCounter, testCounter));
- } else {
- System.err.println(String.format("All %d test cases PASSED!", testCounter));
- }
+ run.checkPassed();
}
}