7179701: MaxJavaStackTraceDepth of zero is not handled correctly/consistently in the VM
Value of zero means unlimited stack trace. If you want no stack trace, use -XX:-StackTraceInThrowable Reviewed-by: dholmes, hseigel
This commit is contained in:
parent
0a10af4b06
commit
7660d97e2e
@ -1968,7 +1968,7 @@ void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHand
|
||||
bool skip_throwableInit_check = false;
|
||||
bool skip_hidden = !ShowHiddenFrames;
|
||||
|
||||
for (frame fr = thread->last_frame(); max_depth != total_count;) {
|
||||
for (frame fr = thread->last_frame(); max_depth == 0 || max_depth != total_count;) {
|
||||
Method* method = NULL;
|
||||
int bci = 0;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2018, 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
|
||||
@ -133,7 +133,7 @@ void vframeStreamForte::forte_next() {
|
||||
// By the time we get here we should never see unsafe but better
|
||||
// safe then segv'd
|
||||
|
||||
if (loop_count > loop_max || !_frame.safe_for_sender(_thread)) {
|
||||
if ((loop_max != 0 && loop_count > loop_max) || !_frame.safe_for_sender(_thread)) {
|
||||
_mode = at_end_mode;
|
||||
return;
|
||||
}
|
||||
@ -324,7 +324,7 @@ static bool find_initial_Java_frame(JavaThread* thread,
|
||||
int loop_max = MaxJavaStackTraceDepth * 2;
|
||||
RegisterMap map(thread, false);
|
||||
|
||||
for (loop_count = 0; loop_count < loop_max; loop_count++) {
|
||||
for (loop_count = 0; loop_max == 0 || loop_count < loop_max; loop_count++) {
|
||||
if (!candidate.safe_for_sender(thread)) return false;
|
||||
candidate = candidate.sender(&map);
|
||||
if (candidate.cb() != NULL) break;
|
||||
@ -338,7 +338,7 @@ static bool find_initial_Java_frame(JavaThread* thread,
|
||||
int loop_max = MaxJavaStackTraceDepth * 2;
|
||||
RegisterMap map(thread, false);
|
||||
|
||||
for (loop_count = 0; loop_count < loop_max; loop_count++) {
|
||||
for (loop_count = 0; loop_max == 0 || loop_count < loop_max; loop_count++) {
|
||||
|
||||
if (candidate.is_entry_frame()) {
|
||||
// jcw is NULL if the java call wrapper couldn't be found
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2018, 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
|
||||
@ -677,7 +677,7 @@ JvmtiEnvBase::get_owned_monitors(JavaThread *calling_thread, JavaThread* java_th
|
||||
int depth = 0;
|
||||
for (javaVFrame *jvf = java_thread->last_java_vframe(®_map); jvf != NULL;
|
||||
jvf = jvf->java_sender()) {
|
||||
if (depth++ < MaxJavaStackTraceDepth) { // check for stack too deep
|
||||
if (MaxJavaStackTraceDepth == 0 || depth++ < MaxJavaStackTraceDepth) { // check for stack too deep
|
||||
// add locked objects for this frame into list
|
||||
err = get_locked_objects_in_frame(calling_thread, java_thread, jvf, owned_monitors_list, depth-1);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2018, 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
|
||||
@ -3200,7 +3200,7 @@ void JavaThread::print_stack_on(outputStream* st) {
|
||||
RegisterMap reg_map(this);
|
||||
vframe* start_vf = last_java_vframe(®_map);
|
||||
int count = 0;
|
||||
for (vframe* f = start_vf; f; f = f->sender()) {
|
||||
for (vframe* f = start_vf; f != NULL; f = f->sender()) {
|
||||
if (f->is_java_frame()) {
|
||||
javaVFrame* jvf = javaVFrame::cast(f);
|
||||
java_lang_Throwable::print_stack_element(st, jvf->method(), jvf->bci());
|
||||
@ -3213,9 +3213,9 @@ void JavaThread::print_stack_on(outputStream* st) {
|
||||
// Ignore non-Java frames
|
||||
}
|
||||
|
||||
// Bail-out case for too deep stacks
|
||||
// Bail-out case for too deep stacks if MaxJavaStackTraceDepth > 0
|
||||
count++;
|
||||
if (MaxJavaStackTraceDepth == count) return;
|
||||
if (MaxJavaStackTraceDepth > 0 && MaxJavaStackTraceDepth == count) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 7179701
|
||||
* @summary MaxJavaStackTraceDepth of zero is not handled correctly/consistently in the VM
|
||||
* @modules java.base/jdk.internal.misc:open
|
||||
* @modules java.base/java.lang:open
|
||||
* @library /test/lib
|
||||
* @run main TestMaxJavaStackTraceDepth runTest
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
|
||||
public class TestMaxJavaStackTraceDepth {
|
||||
|
||||
static final int maxDepth = 2010;
|
||||
|
||||
// Inner class that throws a lot of exceptions
|
||||
static class Thrower {
|
||||
int count = 0;
|
||||
|
||||
int getDepth(Throwable t) throws Exception {
|
||||
Field f = Throwable.class.getDeclaredField("depth");
|
||||
f.setAccessible(true); // it's private
|
||||
return f.getInt(t);
|
||||
}
|
||||
|
||||
void callThrow() throws Exception {
|
||||
if (++count < maxDepth) {
|
||||
callThrow();
|
||||
} else {
|
||||
throw new RuntimeException("depth tested " + maxDepth);
|
||||
}
|
||||
}
|
||||
|
||||
void testThrow() throws Exception {
|
||||
try {
|
||||
count = getDepth(new Throwable()); // count stack to this point.
|
||||
callThrow();
|
||||
} catch(Exception e) {
|
||||
e.getStackTrace();
|
||||
System.out.println(e.getMessage());
|
||||
int throwableDepth = getDepth(e);
|
||||
System.out.println("java.lang.RuntimeException, " + throwableDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
if (args.length > 0) {
|
||||
// Test values of MaxJavaStackTraceDepth
|
||||
int[] depths = {0, 20, 1024};
|
||||
for (int d : depths) {
|
||||
System.out.println("running test with -XX:MaxJavaStackTraceDepth=" + d);
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:stacktrace=info",
|
||||
"-XX:MaxJavaStackTraceDepth=" + d,
|
||||
"--add-opens",
|
||||
"java.base/java.lang=ALL-UNNAMED",
|
||||
"TestMaxJavaStackTraceDepth");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
if (d == 0) {
|
||||
// Should get all the elements in stack trace
|
||||
output.shouldContain("java.lang.RuntimeException, " + maxDepth);
|
||||
} else {
|
||||
output.shouldContain("java.lang.RuntimeException, " + d);
|
||||
}
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
} else {
|
||||
// run the test
|
||||
Thrower t = new Thrower();
|
||||
t.testThrow();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user