Skip to content

Commit 7ece9e9

Browse files
committed
8321400: java/foreign/TestStubAllocFailure.java fails with code cache exhaustion
Reviewed-by: mcimadamore
1 parent 9320ef9 commit 7ece9e9

File tree

7 files changed

+64
-59
lines changed

7 files changed

+64
-59
lines changed

test/jdk/java/foreign/TestAddressDereference.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ public void testNativeUpcallArgNeg(long alignment, ValueLayout layout) throws Th
128128
if (!badAlign) return;
129129
runInNewProcess(UpcallTestRunner.class, true,
130130
new String[] {Long.toString(alignment), layout.toString() })
131-
.assertFailed()
132-
.assertStdErrContains("alignment constraint for address");
131+
.shouldNotHaveExitValue(0)
132+
.stderrShouldContain("alignment constraint for address");
133133
}
134134

135135
public static class UpcallTestRunner {

test/jdk/java/foreign/TestStubAllocFailure.java

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,36 +31,65 @@
3131
*/
3232

3333
import java.lang.foreign.*;
34+
import java.lang.invoke.MethodHandle;
35+
import java.lang.invoke.MethodHandles;
3436
import java.io.IOException;
3537
import java.util.List;
38+
import java.util.function.Consumer;
39+
import java.util.stream.Stream;
3640

3741
import org.testng.annotations.Test;
3842

39-
import static org.testng.Assert.assertTrue;
4043
import static org.testng.Assert.fail;
4144

4245
public class TestStubAllocFailure extends UpcallTestHelper {
4346

4447
@Test
4548
public void testUpcallAllocFailure() throws IOException, InterruptedException {
4649
runInNewProcess(UpcallRunner.class, true, List.of("-XX:ReservedCodeCacheSize=3M"), List.of())
47-
.assertSuccess();
50+
.shouldNotHaveExitValue(0)
51+
.shouldNotHaveFatalError();
52+
}
53+
54+
@Test
55+
public void testUDowncallAllocFailure() throws IOException, InterruptedException {
56+
runInNewProcess(DowncallRunner.class, true, List.of("-XX:ReservedCodeCacheSize=3M"), List.of())
57+
.shouldNotHaveExitValue(0)
58+
.shouldNotHaveFatalError();
4859
}
4960

5061
public static class UpcallRunner extends NativeTestHelper {
5162
public static void main(String[] args) throws Throwable {
52-
try (Arena arena = Arena.ofConfined()) {
53-
while (true) {
54-
// allocate stubs until we crash
55-
upcallStub(UpcallRunner.class, "target", FunctionDescriptor.ofVoid(), arena);
56-
}
57-
} catch (OutOfMemoryError e) {
58-
assertTrue(e.getMessage().contains("Failed to allocate upcall stub"));
63+
FunctionDescriptor descriptor = FunctionDescriptor.ofVoid();
64+
MethodHandle target = MethodHandles.lookup().findStatic(UpcallRunner.class, "target", descriptor.toMethodType());
65+
while (true) {
66+
LINKER.upcallStub(target, descriptor, Arena.ofAuto());
5967
}
6068
}
6169

6270
public static void target() {
6371
fail("Should not get here");
6472
}
6573
}
74+
75+
public static class DowncallRunner extends NativeTestHelper {
76+
77+
private static final int MAX_ARITY = 5;
78+
79+
private static void mapper(FunctionDescriptor fd, Consumer<FunctionDescriptor> sink) {
80+
for (MemoryLayout l : List.of(C_INT, C_LONG_LONG, C_DOUBLE, C_FLOAT, C_SHORT)) {
81+
sink.accept(fd.appendArgumentLayouts(l));
82+
}
83+
}
84+
85+
public static void main(String[] args) throws Throwable {
86+
Linker linker = Linker.nativeLinker();
87+
Stream<FunctionDescriptor> stream = Stream.of(FunctionDescriptor.ofVoid());
88+
for (int i = 0; i < MAX_ARITY; i++) {
89+
stream = stream.mapMulti(DowncallRunner::mapper);
90+
}
91+
92+
stream.forEach(linker::downcallHandle);
93+
}
94+
}
6695
}

test/jdk/java/foreign/TestUpcallException.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ public class TestUpcallException extends UpcallTestHelper {
4848
@Test(dataProvider = "exceptionCases")
4949
public void testException(Class<?> target, boolean useSpec) throws InterruptedException, IOException {
5050
runInNewProcess(target, useSpec)
51-
.assertFailed()
52-
.assertStdErrContains("Testing upcall exceptions");
51+
.shouldNotHaveExitValue(0)
52+
.stderrShouldContain("Testing upcall exceptions");
5353
}
5454

5555
@DataProvider

test/jdk/java/foreign/UpcallTestHelper.java

Lines changed: 7 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -21,54 +21,24 @@
2121
* questions.
2222
*/
2323

24+
import jdk.test.lib.process.OutputAnalyzer;
2425
import jdk.test.lib.process.ProcessTools;
2526
import jdk.test.lib.Utils;
2627

27-
import java.io.BufferedReader;
2828
import java.io.IOException;
29-
import java.io.InputStream;
30-
import java.io.InputStreamReader;
3129
import java.util.ArrayList;
3230
import java.util.List;
3331
import java.util.concurrent.TimeUnit;
3432

35-
import static org.testng.Assert.assertEquals;
36-
import static org.testng.Assert.assertNotEquals;
3733
import static org.testng.Assert.assertTrue;
3834

3935
public class UpcallTestHelper extends NativeTestHelper {
40-
public record Output(int result, List<String> stdout, List<String> stderr) {
41-
private static void assertContains(List<String> lines, String shouldInclude, String name) {
42-
assertTrue(lines.stream().anyMatch(line -> line.contains(shouldInclude)),
43-
"Did not find '" + shouldInclude + "' in " + name);
44-
}
4536

46-
public Output assertFailed() {
47-
assertNotEquals(result, 0);
48-
return this;
49-
}
50-
51-
public Output assertSuccess() {
52-
assertEquals(result, 0);
53-
return this;
54-
}
55-
56-
public Output assertStdErrContains(String shouldInclude) {
57-
assertContains(stderr, shouldInclude, "stderr");
58-
return this;
59-
}
60-
61-
public Output assertStdOutContains(String shouldInclude) {
62-
assertContains(stdout, shouldInclude, "stdout");
63-
return this;
64-
}
65-
}
66-
67-
public Output runInNewProcess(Class<?> target, boolean useSpec, String... programArgs) throws IOException, InterruptedException {
37+
public OutputAnalyzer runInNewProcess(Class<?> target, boolean useSpec, String... programArgs) throws IOException, InterruptedException {
6838
return runInNewProcess(target, useSpec, List.of(), List.of(programArgs));
6939
}
7040

71-
public Output runInNewProcess(Class<?> target, boolean useSpec, List<String> vmArgs, List<String> programArgs) throws IOException, InterruptedException {
41+
public OutputAnalyzer runInNewProcess(Class<?> target, boolean useSpec, List<String> vmArgs, List<String> programArgs) throws IOException, InterruptedException {
7242
assert !target.isArray();
7343

7444
List<String> command = new ArrayList<>(List.of(
@@ -86,17 +56,10 @@ public Output runInNewProcess(Class<?> target, boolean useSpec, List<String> vmA
8656
boolean completed = process.waitFor(timeOut, TimeUnit.MINUTES);
8757
assertTrue(completed, "Time out while waiting for process");
8858

89-
List<String> outLines = linesFromStream(process.getInputStream());
90-
outLines.forEach(System.out::println);
91-
List<String> errLines = linesFromStream(process.getErrorStream());
92-
errLines.forEach(System.err::println);
93-
94-
return new Output(process.exitValue(), outLines, errLines);
95-
}
59+
OutputAnalyzer output = new OutputAnalyzer(process);
60+
output.outputTo(System.out);
61+
output.errorTo(System.err);
9662

97-
private static List<String> linesFromStream(InputStream stream) throws IOException {
98-
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
99-
return reader.lines().toList();
100-
}
63+
return output;
10164
}
10265
}

test/jdk/java/foreign/critical/TestCriticalUpcall.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ public class TestCriticalUpcall extends UpcallTestHelper {
4343
@Test
4444
public void testUpcallFailure() throws IOException, InterruptedException {
4545
// test to see if we catch a trivial downcall doing an upcall
46-
runInNewProcess(Runner.class, true).assertFailed().assertStdOutContains("wrong thread state for upcall");
46+
runInNewProcess(Runner.class, true)
47+
.shouldNotHaveExitValue(0)
48+
.stdoutShouldContain("wrong thread state for upcall");
4749
}
4850

4951
public static class Runner extends NativeTestHelper {

test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ public void testNoHeapArgs() throws Throwable {
5353

5454
@Test(dataProvider = "specs")
5555
public void testNoHeapReturns(boolean spec) throws IOException, InterruptedException {
56-
runInNewProcess(Runner.class, spec).assertFailed().assertStdErrContains("Heap segment not allowed");
56+
runInNewProcess(Runner.class, spec)
57+
.shouldNotHaveExitValue(0)
58+
.stderrShouldContain("Heap segment not allowed");
5759
}
5860

5961
public static class Runner {

test/lib/jdk/test/lib/process/OutputAnalyzer.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public final class OutputAnalyzer {
4242

4343
private static final String deprecatedmsg = ".* VM warning:.* deprecated.*";
4444

45+
private static final String FATAL_ERROR_PAT = "# A fatal error has been detected.*";
46+
4547
private final OutputBuffer buffer;
4648
/**
4749
* Create an OutputAnalyzer, a utility class for verifying output and exit
@@ -862,4 +864,11 @@ public void shouldContainMultiLinePattern(String... needles) {
862864
shouldContainMultiLinePattern(needles, true);
863865
}
864866

867+
/**
868+
* Assert that we did not crash with a hard VM error (generating an hs_err_pidXXX.log)
869+
*/
870+
public void shouldNotHaveFatalError() {
871+
shouldNotMatch(FATAL_ERROR_PAT);
872+
}
873+
865874
}

0 commit comments

Comments
 (0)