1
1
/*
2
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
23
23
24
24
/**
25
25
* @test
26
- * @bug 8309034
26
+ * @bug 8309034 8334545
27
27
* @summary Test that when saving a class initialization failure caused by
28
28
* a StackOverflowError, that we record the SOE as the underlying
29
29
* cause, even if we can't create the ExceptionInInitializerError
30
- * @requires os.simpleArch == "x64"
31
- * @comment The reproducer only fails in the desired way on x64.
32
- * @requires vm.flagless
33
30
* @comment This test could easily be perturbed so don't allow flag settings.
34
- *
35
- * @run main/othervm -Xss160K -Xint TestStackOverflowDuringInit
31
+ * @requires vm.flagless
32
+ * @comment Run with the smallest stack possible to limit the execution time.
33
+ * This is the smallest stack that is supported by all platforms.
34
+ * @run main/othervm -Xss240K -Xint TestStackOverflowDuringInit
36
35
*/
37
36
38
37
import java .io .ByteArrayOutputStream ;
@@ -51,26 +50,54 @@ public class TestStackOverflowDuringInit {
51
50
// of another class, which is where we will fail to create the EIIE.
52
51
// Even then this is non-trivial, only the use of Long.valueOf from
53
52
// the original reproducer seems to trigger SOE in just the right places.
53
+ // Later changes to the JDK meant that LongCache was initialized before
54
+ // the test even started under jtreg so we define local versions.
55
+
56
+ static class LongCache {
57
+ // Must have a static initializer
58
+ static {
59
+ System .out .println ("LongCache is initializing" );
60
+ }
61
+ static java .lang .Long valueOf (long l ) {
62
+ return Long .valueOf (l );
63
+ }
64
+ }
65
+
66
+ static class MyLong {
67
+ static java .lang .Long valueOf (long l ) {
68
+ if (l > -128 && l < 127 ) {
69
+ return LongCache .valueOf (l );
70
+ } else {
71
+ return Long .valueOf (l );
72
+ }
73
+ }
74
+ }
54
75
55
76
static void recurse () {
56
77
try {
57
- // This will initialize Long but not touch LongCache.
58
- Long .valueOf (1024L );
78
+ // This will initialize MyLong but not touch LongCache.
79
+ MyLong .valueOf (1024L );
59
80
recurse ();
60
81
} finally {
61
82
// This will require initializing LongCache, which will
62
83
// initially fail due to StackOverflowError and so LongCache
63
84
// will be marked erroneous. As we unwind and again execute this
64
85
// we will throw NoClassDefFoundError due to the erroneous
65
86
// state of LongCache.
66
- Long .valueOf (0 );
87
+ MyLong .valueOf (0 );
67
88
}
68
89
}
69
90
70
91
public static void main (String [] args ) throws Exception {
71
- String expected = "java.lang.NoClassDefFoundError: Could not initialize class java.lang.Long $LongCache" ;
92
+ String expected = "java.lang.NoClassDefFoundError: Could not initialize class TestStackOverflowDuringInit $LongCache" ;
72
93
String cause = "Caused by: java.lang.StackOverflowError" ;
73
94
95
+ // Pre-load, but not initialize, LongCache, else we will
96
+ // hit SOE during class loading.
97
+ System .out .println ("Pre-loading ..." );
98
+ Class <?> c = Class .forName ("TestStackOverflowDuringInit$LongCache" ,
99
+ false ,
100
+ TestStackOverflowDuringInit .class .getClassLoader ());
74
101
try {
75
102
recurse ();
76
103
} catch (Throwable ex ) {
0 commit comments