Skip to content

Commit 829cbc2

Browse files
author
David Holmes
committed
8292674: ReportJNIFatalError should print all java frames
Reviewed-by: pchilanomate
1 parent be69930 commit 829cbc2

File tree

6 files changed

+93
-17
lines changed

6 files changed

+93
-17
lines changed

src/hotspot/share/prims/jni.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ JNI_ENTRY(void, jni_FatalError(JNIEnv *env, const char *msg))
626626
HOTSPOT_JNI_FATALERROR_ENTRY(env, (char *) msg);
627627

628628
tty->print_cr("FATAL ERROR in native method: %s", msg);
629-
thread->print_stack();
629+
thread->print_jni_stack();
630630
os::abort(); // Dump core and abort
631631
JNI_END
632632

src/hotspot/share/prims/jniCheck.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ static const char * fatal_non_utf8_class_name2 = "\"";
142142
// When in VM state:
143143
static void ReportJNIWarning(JavaThread* thr, const char *msg) {
144144
tty->print_cr("WARNING in native method: %s", msg);
145-
thr->print_stack();
145+
thr->print_jni_stack();
146146
}
147147

148148
// When in NATIVE state:
@@ -193,7 +193,7 @@ check_pending_exception(JavaThread* thr) {
193193
IN_VM(
194194
tty->print_cr("WARNING in native method: JNI call made without checking exceptions when required to from %s",
195195
thr->get_pending_jni_exception_check());
196-
thr->print_stack();
196+
thr->print_jni_stack();
197197
)
198198
thr->clear_pending_jni_exception_check(); // Just complain once
199199
}

src/hotspot/share/prims/jniCheck.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@ extern "C" {
3535
// When in VM state:
3636
static inline void ReportJNIFatalError(JavaThread* thr, const char *msg) {
3737
tty->print_cr("FATAL ERROR in native method: %s", msg);
38-
thr->print_stack();
38+
thr->print_jni_stack();
3939
os::abort(true);
4040
}
4141
}

src/hotspot/share/runtime/javaThread.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,16 @@ oop JavaThread::current_park_blocker() {
16731673
return NULL;
16741674
}
16751675

1676+
// Print stack trace for checked JNI warnings and JNI fatal errors.
1677+
// This is the external format from above, but selecting the platform
1678+
// or vthread as applicable.
1679+
void JavaThread::print_jni_stack() {
1680+
if (is_vthread_mounted()) {
1681+
print_vthread_stack_on(tty);
1682+
} else {
1683+
print_stack_on(tty);
1684+
}
1685+
}
16761686

16771687
void JavaThread::print_stack_on(outputStream* st) {
16781688
if (!has_last_Java_frame()) return;
@@ -1706,6 +1716,48 @@ void JavaThread::print_stack_on(outputStream* st) {
17061716
}
17071717
}
17081718

1719+
void JavaThread::print_vthread_stack_on(outputStream* st) {
1720+
assert(is_vthread_mounted(), "Caller should have checked this");
1721+
assert(has_last_Java_frame(), "must be");
1722+
1723+
Thread* current_thread = Thread::current();
1724+
ResourceMark rm(current_thread);
1725+
HandleMark hm(current_thread);
1726+
1727+
RegisterMap reg_map(this,
1728+
RegisterMap::UpdateMap::include,
1729+
RegisterMap::ProcessFrames::include,
1730+
RegisterMap::WalkContinuation::include);
1731+
ContinuationEntry* cont_entry = last_continuation();
1732+
vframe* start_vf = last_java_vframe(&reg_map);
1733+
int count = 0;
1734+
for (vframe* f = start_vf; f != NULL; f = f->sender()) {
1735+
// Watch for end of vthread stack
1736+
if (Continuation::is_continuation_enterSpecial(f->fr())) {
1737+
assert(cont_entry == Continuation::get_continuation_entry_for_entry_frame(this, f->fr()), "");
1738+
if (cont_entry->is_virtual_thread()) {
1739+
break;
1740+
}
1741+
cont_entry = cont_entry->parent();
1742+
}
1743+
if (f->is_java_frame()) {
1744+
javaVFrame* jvf = javaVFrame::cast(f);
1745+
java_lang_Throwable::print_stack_element(st, jvf->method(), jvf->bci());
1746+
1747+
// Print out lock information
1748+
if (JavaMonitorsInStackTrace) {
1749+
jvf->print_lock_info_on(st, count);
1750+
}
1751+
} else {
1752+
// Ignore non-Java frames
1753+
}
1754+
1755+
// Bail-out case for too deep stacks if MaxJavaStackTraceDepth > 0
1756+
count++;
1757+
if (MaxJavaStackTraceDepth > 0 && MaxJavaStackTraceDepth == count) return;
1758+
}
1759+
}
1760+
17091761
#if INCLUDE_JVMTI
17101762
// Rebind JVMTI thread state from carrier to virtual or from virtual to carrier.
17111763
JvmtiThreadState* JavaThread::rebind_to_jvmti_thread_state_of(oop thread_oop) {

src/hotspot/share/runtime/javaThread.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,12 @@ class JavaThread: public Thread {
940940
// Print stack trace in external format
941941
void print_stack_on(outputStream* st);
942942
void print_stack() { print_stack_on(tty); }
943+
void print_vthread_stack_on(outputStream* st);
944+
945+
// Print stack trace for checked JNI warnings and JNI fatal errors.
946+
// This is the external format from above, but selecting the platform
947+
// or vthread as applicable.
948+
void print_jni_stack();
943949

944950
// Print stack traces in various internal formats
945951
void trace_stack() PRODUCT_RETURN;

test/hotspot/jtreg/runtime/jni/checked/TestPrimitiveArrayCriticalWithBadParam.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2021, Red Hat, Inc. All rights reserved.
3+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -24,9 +25,11 @@
2425

2526
/**
2627
* @test TestPrimitiveArrayCriticalWithBadParam
27-
* @bug 8269697
28+
* @bug 8269697 8292674
2829
* @summary -Xcheck:jni should catch wrong parameter passed to GetPrimitiveArrayCritical
30+
* @comment Tests reporting with regular thread and virtual thread.
2931
* @library /test/lib
32+
* @enablePreview
3033
* @run main/native TestPrimitiveArrayCriticalWithBadParam
3134
*/
3235
import java.util.List;
@@ -47,39 +50,54 @@ public class TestPrimitiveArrayCriticalWithBadParam {
4750

4851
public static void main(String[] args) {
4952
if (args.length > 0) {
50-
test();
53+
test(args[0]);
5154
} else {
52-
runTest();
55+
runTest(false);
56+
runTest(true);
5357
}
5458
}
5559

56-
private static void runTest() {
60+
private static void runTest(boolean useVThread) {
5761
List<String> pbArgs = new ArrayList<>();
5862
pbArgs.add("-XX:-CreateCoredumpOnCrash");
5963
pbArgs.add("-Xcheck:jni");
64+
pbArgs.add("--enable-preview");
6065
pbArgs.add("-Djava.library.path=" + Utils.TEST_NATIVE_PATH);
6166
pbArgs.add(TestPrimitiveArrayCriticalWithBadParam.class.getName());
62-
pbArgs.add("test");
67+
pbArgs.add(useVThread ? "vtest" : "test");
6368
try {
6469
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(pbArgs.toArray(new String[0]));
6570
OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
6671

6772
// -Xcheck:jni should warn the bad parameter
6873
analyzer.shouldContain("FATAL ERROR in native method: Primitive type array expected but not received for JNI array operation");
74+
analyzer.shouldContain("TestPrimitiveArrayCriticalWithBadParam.pin");
6975
analyzer.shouldNotHaveExitValue(0);
7076
} catch (IOException e) {
7177
throw new RuntimeException(e);
7278
}
7379
}
7480

75-
private static void test() {
76-
Object[] objs = new Object[10];
77-
for (int i = 0; i < objs.length; i++) {
78-
objs[i] = new MyClass();
81+
private static void test(String mode) {
82+
Runnable r = () -> {
83+
Object[] objs = new Object[10];
84+
for (int i = 0; i < objs.length; i++) {
85+
objs[i] = new MyClass();
86+
}
87+
pin(objs);
88+
System.out.println("Object array pinned");
89+
unpin(objs);
90+
};
91+
if (mode.equals("vtest")) {
92+
Thread t = Thread.ofVirtual().start(r);
93+
try {
94+
t.join();
95+
} catch (InterruptedException ex) {
96+
throw new Error("unexpected", ex);
97+
}
98+
} else {
99+
r.run();
79100
}
80-
pin(objs);
81-
System.out.println("Object array pinned");
82-
unpin(objs);
83101
}
84102
public static class MyClass {
85103
public Object ref = new Object();

0 commit comments

Comments
 (0)