diff --git a/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java b/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java index 674affeded1..43a9985d835 100644 --- a/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java +++ b/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java @@ -32,7 +32,7 @@ * @requires vm.flagless * @comment This test could easily be perturbed so don't allow flag settings. * - * @run main/othervm TestStackOverflowDuringInit + * @run main/othervm -Xss160K -Xint TestStackOverflowDuringInit */ import java.io.ByteArrayOutputStream; @@ -40,23 +40,45 @@ import java.io.PrintStream; public class TestStackOverflowDuringInit { - // Test case is fuzzed/obfuscated + // The setup for this is somewhat intricate. We need to trigger a + // StackOverflowError during execution of the static initializer + // for a class, but we need there to be insufficient stack left + // for the creation of the ExceptionInInitializerError that would + // occur in that case. So we can't just recurse in a static initializer + // as that would unwind all the way allowing plenty of stack for the + // EIIE. Instead we recurse outside of a static initializer context + // and have a finally clause that will trigger class initialization + // of another class, which is where we will fail to create the EIIE. + // Even then this is non-trivial, only the use of Long.valueOf from + // the original reproducer seems to trigger SOE in just the right places. + + static void recurse() { + try { + // This will initialize Long but not touch LongCache. + Long.valueOf(1024L); + recurse(); + } finally { + // This will require initializing LongCache, which will + // initially fail due to StackOverflowError and so LongCache + // will be marked erroneous. As we unwind and again execute this + // we will throw NoClassDefFoundError due to the erroneous + // state of LongCache. + Long.valueOf(0); + } + } public static void main(String[] args) throws Exception { String expected = "java.lang.NoClassDefFoundError: Could not initialize class java.lang.Long$LongCache"; String cause = "Caused by: java.lang.StackOverflowError"; - TestStackOverflowDuringInit i = new TestStackOverflowDuringInit(); try { - i.j(); + recurse(); } catch (Throwable ex) { // ex.printStackTrace(); verify_stack(ex, expected, cause); } } - void j() { ((e) new a()).g = 0; } - private static void verify_stack(Throwable e, String expected, String cause) throws Exception { ByteArrayOutputStream byteOS = new ByteArrayOutputStream(); try (PrintStream printStream = new PrintStream(byteOS)) { @@ -70,22 +92,3 @@ public class TestStackOverflowDuringInit { } } } - -class a { - Boolean b; - { - try { - Long.valueOf(509505376256L); - Boolean c = - true ? new d().b - : 5 != ((e)java.util.HashSet.newHashSet(301758).clone()).f; - } finally { - Long.valueOf(0); - } - } -} -class e extends a { - double g; - int f; -} -class d extends a {}