From 6bac7485a6a561e15118279a39c345b484d94edb Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 23 Apr 2025 19:51:41 +0800 Subject: [PATCH 01/18] add Throwable benchmark --- .../openjdk/bench/java/lang/Throwables.java | 177 ++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 test/micro/org/openjdk/bench/java/lang/Throwables.java diff --git a/test/micro/org/openjdk/bench/java/lang/Throwables.java b/test/micro/org/openjdk/bench/java/lang/Throwables.java new file mode 100644 index 0000000000000..096dae9af8376 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/Throwables.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2025, Alibaba Group Holding Limited. 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. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS) +@Fork(3) +public class Throwables { + private OutputStream byteArrayOutputStream; + + @Setup + public void setup() { + byteArrayOutputStream = new OutputStream() { + @Override + public void write(int b) throws IOException {} + }; + } + + @Benchmark + public PrintStream printStackTrace() { + Exception error = null; + try { + x0(); + } catch (Exception e1) { + error = e1; + } + PrintStream printStream = new PrintStream(byteArrayOutputStream); + error.printStackTrace(printStream); + return printStream; + } + + @Benchmark + public PrintStream printEnclosedStackTrace() { + Exception error = null; + try { + f0(); + } catch (Exception e1) { + error = e1; + } + PrintStream printStream = new PrintStream(byteArrayOutputStream); + error.printStackTrace(printStream); + return printStream; + } + + private static void fN() { + throw new RuntimeException(); + } + + private static void f9() { + fN(); + } + + private static void f8() { + f9(); + } + + private static void f7() { + f8(); + } + + private static void f6() { + f7(); + } + + private static void f5() { + f6(); + } + + private static void f4() { + f5(); + } + + private static void f3() { + f4(); + } + + private static void f2() { + f3(); + } + + private static void f1() { + f2(); + } + + private static void f0() { + f1(); + } + + private static void xn() { + try { + f0(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void x9() { + xn(); + } + + private static void x8() { + x9(); + } + + private static void x7() { + x8(); + } + + private static void x6() { + x7(); + } + + private static void x5() { + x6(); + } + + private static void x4() { + x5(); + } + + private static void x3() { + x4(); + } + + private static void x2() { + x3(); + } + + private static void x1() { + x2(); + } + + private static void x0() { + x1(); + } +} From 6ff81aff9ed8354b12680572618a406fb2500e1b Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 23 Apr 2025 19:56:28 +0800 Subject: [PATCH 02/18] Speed up printStackTrace by reducing StringBuilder and IdentityHashMap allocations --- .../classes/java/lang/StackTraceElement.java | 22 +++-- .../share/classes/java/lang/Throwable.java | 96 +++++++++++++++---- 2 files changed, 94 insertions(+), 24 deletions(-) diff --git a/src/java.base/share/classes/java/lang/StackTraceElement.java b/src/java.base/share/classes/java/lang/StackTraceElement.java index 70219a7f6ec3a..0ca6efd251735 100644 --- a/src/java.base/share/classes/java/lang/StackTraceElement.java +++ b/src/java.base/share/classes/java/lang/StackTraceElement.java @@ -358,15 +358,27 @@ public boolean isNativeMethod() { */ @Override public String toString() { - int estimatedLength = length(classLoaderName) + 1 + return appendTo( + new StringBuilder( + estimatedLength())) + .toString(); + } + + int estimatedLength() { + return length(classLoaderName) + 1 + length(moduleName) + 1 + length(moduleVersion) + 1 + declaringClass.length() + 1 + methodName.length() + 1 + Math.max(UNKNOWN_SOURCE.length(), length(fileName)) + 1 + 12; + } - StringBuilder sb = new StringBuilder(estimatedLength); + /** + * Prints the toString result to the given buf, avoiding extra string allocations. + */ + StringBuilder appendTo(StringBuilder sb) { + int length = sb.length(); if (!dropClassLoaderName() && classLoaderName != null && !classLoaderName.isEmpty()) { sb.append(classLoaderName).append('/'); } @@ -378,7 +390,7 @@ public String toString() { } } - if (sb.length() > 0) { + if (sb.length() != length) { sb.append('/'); } @@ -393,9 +405,7 @@ public String toString() { sb.append(':').append(lineNumber); } } - sb.append(')'); - - return sb.toString(); + return sb.append(')'); } private static int length(String s) { diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 8c0ce29dbeefc..a3702bb3379f8 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, 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 @@ -687,41 +687,59 @@ public void printStackTrace(PrintStream s) { } private void printStackTrace(PrintStreamOrWriter s) { - // Guard against malicious overrides of Throwable.equals by - // using a Set with identity equality semantics. - Set dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); - dejaVu.add(this); + /* + * Guard against malicious overrides of Throwable.equals by + * using a Set with identity equality semantics. + */ + Set dejaVu = null; synchronized(s.lock()) { // Print our stack trace s.println(this); StackTraceElement[] trace = getOurStackTrace(); - for (StackTraceElement traceElement : trace) - s.println("\tat " + traceElement); + printStackTrace0(s, trace); // Print suppressed exceptions, if any - for (Throwable se : getSuppressed()) - se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); + java.lang.Throwable[] suppressed = getSuppressed(); + if (suppressed.length > 0) { + dejaVu = dejaVu(); + } + for (Throwable se : suppressed) + se.printEnclosedStackTrace(s, trace, "\t".concat(SUPPRESSED_CAPTION), "\t", dejaVu); // Print cause, if any Throwable ourCause = getCause(); - if (ourCause != null) + if (ourCause != null) { + if (dejaVu == null) { + dejaVu = dejaVu(); + } ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); + } } } + /** + * Guard against malicious overrides of Throwable.equals by + * using a Set with identity equality semantics. + */ + private Set dejaVu() { + Set dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); + dejaVu.add(this); + return dejaVu; + } + /** * Print our stack trace as an enclosed exception for the specified * stack trace. */ private void printEnclosedStackTrace(PrintStreamOrWriter s, StackTraceElement[] enclosingTrace, - String caption, + String prefixCaption, String prefix, Set dejaVu) { assert Thread.holdsLock(s.lock()); if (dejaVu.contains(this)) { - s.println(prefix + caption + "[CIRCULAR REFERENCE: " + this + "]"); + s.println(prefixCaption + "[CIRCULAR REFERENCE: " + this + "]"); } else { dejaVu.add(this); // Compute number of frames in common between this and enclosing trace @@ -734,16 +752,13 @@ private void printEnclosedStackTrace(PrintStreamOrWriter s, int framesInCommon = trace.length - 1 - m; // Print our stack trace - s.println(prefix + caption + this); - for (int i = 0; i <= m; i++) - s.println(prefix + "\tat " + trace[i]); - if (framesInCommon != 0) - s.println(prefix + "\t... " + framesInCommon + " more"); + s.println(prefixCaption.concat(this.toString())); + printStackTrace0(s, prefix, trace, m, framesInCommon); // Print suppressed exceptions, if any for (Throwable se : getSuppressed()) se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, - prefix +"\t", dejaVu); + prefix.concat("\t"), dejaVu); // Print cause, if any Throwable ourCause = getCause(); @@ -763,6 +778,51 @@ public void printStackTrace(PrintWriter s) { printStackTrace(new WrappedPrintWriter(s)); } + /** + * Use a StringBuilder to print multiple StackTraceElements + */ + private static void printStackTrace0(PrintStreamOrWriter printer, StackTraceElement[] trace) { + printStackTrace0(printer, null, trace, trace.length - 1, 0); + } + + /** + * Use a StringBuilder to print multiple StackTraceElements + */ + private static void printStackTrace0( + PrintStreamOrWriter printer, + String prefix, + StackTraceElement[] trace, + int traceEnd, + int framesInCommon) { + String at = "\tat "; + int prefixAndAtLength = at.length(); + if (prefix != null) { + prefixAndAtLength += prefix.length(); + } + + var sb = new StringBuilder(128); + if (prefix != null) { + sb.append(prefix); + } + sb.append(at); + for (int i = 0; i <= traceEnd; i++) { + if (i != 0) { + sb.delete(prefixAndAtLength, sb.length()); + } + printer.println(trace[i] + .appendTo(sb) + .toString()); + } + + if (framesInCommon != 0) { + sb.delete(prefix.length(), sb.length()) + .append("\t... ") + .append(framesInCommon) + .append(" more"); + printer.println(sb.toString()); + } + } + /** * Wrapper class for PrintStream and PrintWriter to enable a single * implementation of printStackTrace. From a96df2270474457881c3dfaab85886bee1288d18 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 25 Apr 2025 10:01:16 +0800 Subject: [PATCH 03/18] from @liach --- .../share/classes/java/lang/Throwable.java | 36 +++++++------------ 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index a3702bb3379f8..72294e93e75bc 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -687,47 +687,37 @@ public void printStackTrace(PrintStream s) { } private void printStackTrace(PrintStreamOrWriter s) { - /* - * Guard against malicious overrides of Throwable.equals by - * using a Set with identity equality semantics. - */ - Set dejaVu = null; - synchronized(s.lock()) { // Print our stack trace s.println(this); StackTraceElement[] trace = getOurStackTrace(); printStackTrace0(s, trace); - // Print suppressed exceptions, if any java.lang.Throwable[] suppressed = getSuppressed(); - if (suppressed.length > 0) { - dejaVu = dejaVu(); + Throwable ourCause = getCause(); + + /* + * Guard against malicious overrides of Throwable.equals by + * using a Set with identity equality semantics. + */ + Set dejaVu = null; + if (suppressed.length > 0 || ourCause != null) { + dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); + dejaVu.add(this); } + + // Print suppressed exceptions, if any for (Throwable se : suppressed) se.printEnclosedStackTrace(s, trace, "\t".concat(SUPPRESSED_CAPTION), "\t", dejaVu); // Print cause, if any - Throwable ourCause = getCause(); + if (ourCause != null) { - if (dejaVu == null) { - dejaVu = dejaVu(); - } ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); } } } - /** - * Guard against malicious overrides of Throwable.equals by - * using a Set with identity equality semantics. - */ - private Set dejaVu() { - Set dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); - dejaVu.add(this); - return dejaVu; - } - /** * Print our stack trace as an enclosed exception for the specified * stack trace. From 80b76ece1e4ff6a8c3fb6357c1e5875a81ed74e4 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 25 Apr 2025 10:03:29 +0800 Subject: [PATCH 04/18] from @liach --- .../share/classes/java/lang/Throwable.java | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 72294e93e75bc..9aa4f2b07efaa 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -696,24 +696,23 @@ private void printStackTrace(PrintStreamOrWriter s) { java.lang.Throwable[] suppressed = getSuppressed(); Throwable ourCause = getCause(); - /* - * Guard against malicious overrides of Throwable.equals by - * using a Set with identity equality semantics. - */ - Set dejaVu = null; if (suppressed.length > 0 || ourCause != null) { - dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); + /* + * Guard against malicious overrides of Throwable.equals by + * using a Set with identity equality semantics. + */ + Set dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); dejaVu.add(this); - } - // Print suppressed exceptions, if any - for (Throwable se : suppressed) - se.printEnclosedStackTrace(s, trace, "\t".concat(SUPPRESSED_CAPTION), "\t", dejaVu); + // Print suppressed exceptions, if any + for (Throwable se : suppressed) + se.printEnclosedStackTrace(s, trace, "\t".concat(SUPPRESSED_CAPTION), "\t", dejaVu); - // Print cause, if any + // Print cause, if any - if (ourCause != null) { - ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); + if (ourCause != null) { + ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); + } } } } From ad677dd921e0cf8fd12acbf38ccfbe0094d45f2f Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 25 Apr 2025 10:12:09 +0800 Subject: [PATCH 05/18] from @liach --- .../share/classes/java/lang/Throwable.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 9aa4f2b07efaa..f891bb4dd8ab8 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -783,20 +783,15 @@ private static void printStackTrace0( StackTraceElement[] trace, int traceEnd, int framesInCommon) { - String at = "\tat "; - int prefixAndAtLength = at.length(); - if (prefix != null) { - prefixAndAtLength += prefix.length(); - } - var sb = new StringBuilder(128); if (prefix != null) { sb.append(prefix); } - sb.append(at); + sb.append("\tat "); + int prefixAndAtLength = sb.length(); for (int i = 0; i <= traceEnd; i++) { if (i != 0) { - sb.delete(prefixAndAtLength, sb.length()); + sb.setLength(prefixAndAtLength); } printer.println(trace[i] .appendTo(sb) @@ -804,8 +799,8 @@ private static void printStackTrace0( } if (framesInCommon != 0) { - sb.delete(prefix.length(), sb.length()) - .append("\t... ") + sb.setLength(prefix == null ? 0 : prefix.length()); + sb.append("\t... ") .append(framesInCommon) .append(" more"); printer.println(sb.toString()); From 8652492c8aef81deba503c275f47d7df886c3b76 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 25 Apr 2025 10:37:07 +0800 Subject: [PATCH 06/18] Remove redundant toString --- src/java.base/share/classes/java/lang/Throwable.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index f891bb4dd8ab8..81aa2db5267bc 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -794,16 +794,15 @@ private static void printStackTrace0( sb.setLength(prefixAndAtLength); } printer.println(trace[i] - .appendTo(sb) - .toString()); + .appendTo(sb)); } if (framesInCommon != 0) { sb.setLength(prefix == null ? 0 : prefix.length()); - sb.append("\t... ") - .append(framesInCommon) - .append(" more"); - printer.println(sb.toString()); + printer.println( + sb.append("\t... ") + .append(framesInCommon) + .append(" more")); } } From f50bb31805a4492c85b9c047f18efaa695739988 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 25 Apr 2025 11:25:16 +0800 Subject: [PATCH 07/18] from @liach --- .../classes/java/lang/StackTraceElement.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/java.base/share/classes/java/lang/StackTraceElement.java b/src/java.base/share/classes/java/lang/StackTraceElement.java index 0ca6efd251735..104dfae246ce5 100644 --- a/src/java.base/share/classes/java/lang/StackTraceElement.java +++ b/src/java.base/share/classes/java/lang/StackTraceElement.java @@ -358,27 +358,23 @@ public boolean isNativeMethod() { */ @Override public String toString() { - return appendTo( - new StringBuilder( - estimatedLength())) - .toString(); - } - - int estimatedLength() { - return length(classLoaderName) + 1 + int estimatedLength = length(classLoaderName) + 1 + length(moduleName) + 1 + length(moduleVersion) + 1 + declaringClass.length() + 1 + methodName.length() + 1 + Math.max(UNKNOWN_SOURCE.length(), length(fileName)) + 1 + 12; + return appendTo( + new StringBuilder(estimatedLength)) + .toString(); } /** * Prints the toString result to the given buf, avoiding extra string allocations. */ StringBuilder appendTo(StringBuilder sb) { - int length = sb.length(); + int startingLength = sb.length(); if (!dropClassLoaderName() && classLoaderName != null && !classLoaderName.isEmpty()) { sb.append(classLoaderName).append('/'); } @@ -390,7 +386,7 @@ StringBuilder appendTo(StringBuilder sb) { } } - if (sb.length() != length) { + if (sb.length() != startingLength) { sb.append('/'); } From 19793b9735e285f5bf1b824b9300a6a82222da2d Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 25 Apr 2025 11:29:33 +0800 Subject: [PATCH 08/18] Update src/java.base/share/classes/java/lang/Throwable.java Co-authored-by: Chen Liang --- src/java.base/share/classes/java/lang/Throwable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 81aa2db5267bc..6be27ef4a4ad6 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -693,7 +693,7 @@ private void printStackTrace(PrintStreamOrWriter s) { StackTraceElement[] trace = getOurStackTrace(); printStackTrace0(s, trace); - java.lang.Throwable[] suppressed = getSuppressed(); + Throwable[] suppressed = getSuppressed(); Throwable ourCause = getCause(); if (suppressed.length > 0 || ourCause != null) { From 02eb4d61da3ac8f36b2c07690fc478ce1a86f2a4 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 25 Apr 2025 11:36:49 +0800 Subject: [PATCH 09/18] from @liach --- src/java.base/share/classes/java/lang/Throwable.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 6be27ef4a4ad6..21752f5cb1122 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -706,7 +706,7 @@ private void printStackTrace(PrintStreamOrWriter s) { // Print suppressed exceptions, if any for (Throwable se : suppressed) - se.printEnclosedStackTrace(s, trace, "\t".concat(SUPPRESSED_CAPTION), "\t", dejaVu); + se.printEnclosedStackTrace(s, trace, "\t" + SUPPRESSED_CAPTION, "\t", dejaVu); // Print cause, if any @@ -738,11 +738,10 @@ private void printEnclosedStackTrace(PrintStreamOrWriter s, while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) { m--; n--; } - int framesInCommon = trace.length - 1 - m; // Print our stack trace s.println(prefixCaption.concat(this.toString())); - printStackTrace0(s, prefix, trace, m, framesInCommon); + printStackTrace0(s, prefix, trace, m); // Print suppressed exceptions, if any for (Throwable se : getSuppressed()) @@ -771,7 +770,7 @@ public void printStackTrace(PrintWriter s) { * Use a StringBuilder to print multiple StackTraceElements */ private static void printStackTrace0(PrintStreamOrWriter printer, StackTraceElement[] trace) { - printStackTrace0(printer, null, trace, trace.length - 1, 0); + printStackTrace0(printer, null, trace, trace.length - 1); } /** @@ -781,8 +780,7 @@ private static void printStackTrace0( PrintStreamOrWriter printer, String prefix, StackTraceElement[] trace, - int traceEnd, - int framesInCommon) { + int traceEnd) { var sb = new StringBuilder(128); if (prefix != null) { sb.append(prefix); @@ -797,6 +795,7 @@ private static void printStackTrace0( .appendTo(sb)); } + int framesInCommon = trace.length - 1 - traceEnd; if (framesInCommon != 0) { sb.setLength(prefix == null ? 0 : prefix.length()); printer.println( From 18b576f0d335ce9ea43dab293625992e29ef4717 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 25 Apr 2025 11:44:27 +0800 Subject: [PATCH 10/18] bug fix --- .../share/classes/java/lang/Throwable.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 21752f5cb1122..4f36d459122ae 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -744,14 +744,19 @@ private void printEnclosedStackTrace(PrintStreamOrWriter s, printStackTrace0(s, prefix, trace, m); // Print suppressed exceptions, if any - for (Throwable se : getSuppressed()) - se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, - prefix.concat("\t"), dejaVu); + Throwable[] suppressed = getSuppressed(); + if (suppressed != null) { + String prefixT = prefix.concat("\t"); + for (Throwable se : suppressed) { + se.printEnclosedStackTrace(s, trace, prefixT.concat(SUPPRESSED_CAPTION), + prefixT, dejaVu); + } + } // Print cause, if any Throwable ourCause = getCause(); if (ourCause != null) - ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu); + ourCause.printEnclosedStackTrace(s, trace, prefix.concat(CAUSE_CAPTION), prefix, dejaVu); } } From f1a4279e7ecea91149f8e90d28c1b524b6f1012a Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 25 Apr 2025 11:48:22 +0800 Subject: [PATCH 11/18] bug fix --- src/java.base/share/classes/java/lang/Throwable.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 4f36d459122ae..74ca5029a711e 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -744,14 +744,9 @@ private void printEnclosedStackTrace(PrintStreamOrWriter s, printStackTrace0(s, prefix, trace, m); // Print suppressed exceptions, if any - Throwable[] suppressed = getSuppressed(); - if (suppressed != null) { - String prefixT = prefix.concat("\t"); - for (Throwable se : suppressed) { - se.printEnclosedStackTrace(s, trace, prefixT.concat(SUPPRESSED_CAPTION), - prefixT, dejaVu); - } - } + for (Throwable se : getSuppressed()) + se.printEnclosedStackTrace(s, trace, prefix.concat("\t" + SUPPRESSED_CAPTION), + prefix.concat("\t"), dejaVu); // Print cause, if any Throwable ourCause = getCause(); From a68c693218a39cb7fd968fff5d05f03ef592f787 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sat, 26 Apr 2025 10:48:26 +0800 Subject: [PATCH 12/18] lineBuffer, from @liach --- .../share/classes/java/lang/Throwable.java | 90 +++++++++---------- 1 file changed, 40 insertions(+), 50 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 74ca5029a711e..891863b101070 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -690,11 +690,21 @@ private void printStackTrace(PrintStreamOrWriter s) { synchronized(s.lock()) { // Print our stack trace s.println(this); + var lineBuffer = new StringBuilder(128); // arbitrary size + lineBuffer.append("\tat "); + int prefixLen = lineBuffer.length(); + StackTraceElement[] trace = getOurStackTrace(); - printStackTrace0(s, trace); + for (int i = 0; i < trace.length; i++) { + if (i != 0) { + lineBuffer.setLength(prefixLen); + } + trace[i].appendTo(lineBuffer); + s.println(lineBuffer.toString()); + } - Throwable[] suppressed = getSuppressed(); - Throwable ourCause = getCause(); + var suppressed = getSuppressed(); + var ourCause = getCause(); if (suppressed.length > 0 || ourCause != null) { /* @@ -706,12 +716,12 @@ private void printStackTrace(PrintStreamOrWriter s) { // Print suppressed exceptions, if any for (Throwable se : suppressed) - se.printEnclosedStackTrace(s, trace, "\t" + SUPPRESSED_CAPTION, "\t", dejaVu); + se.printEnclosedStackTrace(s, lineBuffer, trace, SUPPRESSED_CAPTION, "\t", dejaVu); // Print cause, if any if (ourCause != null) { - ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); + ourCause.printEnclosedStackTrace(s, lineBuffer, trace, CAUSE_CAPTION, "", dejaVu); } } } @@ -722,13 +732,16 @@ private void printStackTrace(PrintStreamOrWriter s) { * stack trace. */ private void printEnclosedStackTrace(PrintStreamOrWriter s, + StringBuilder lineBuffer, StackTraceElement[] enclosingTrace, - String prefixCaption, + String caption, String prefix, Set dejaVu) { assert Thread.holdsLock(s.lock()); + lineBuffer.setLength(0); if (dejaVu.contains(this)) { - s.println(prefixCaption + "[CIRCULAR REFERENCE: " + this + "]"); + s.println( + lineBuffer.append(prefix).append(caption).append("[CIRCULAR REFERENCE: ").append(this).append("]")); } else { dejaVu.add(this); // Compute number of frames in common between this and enclosing trace @@ -738,20 +751,36 @@ private void printEnclosedStackTrace(PrintStreamOrWriter s, while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) { m--; n--; } + int framesInCommon = trace.length - 1 - m; // Print our stack trace - s.println(prefixCaption.concat(this.toString())); - printStackTrace0(s, prefix, trace, m); + s.println( + lineBuffer.append(prefix).append(caption).append(this)); + lineBuffer.setLength(prefix.length()); + lineBuffer.append("\tat "); + int indent = lineBuffer.length(); + for (int i = 0; i <= m; i++) { + if (i != 0) { + lineBuffer.setLength(indent); + } + s.println( + trace[i].appendTo(lineBuffer)); + } + if (framesInCommon != 0) { + lineBuffer.setLength(prefix.length()); + s.println( + lineBuffer.append("\t... ").append(framesInCommon).append(" more")); + } // Print suppressed exceptions, if any for (Throwable se : getSuppressed()) - se.printEnclosedStackTrace(s, trace, prefix.concat("\t" + SUPPRESSED_CAPTION), + se.printEnclosedStackTrace(s, lineBuffer, trace, SUPPRESSED_CAPTION, prefix.concat("\t"), dejaVu); // Print cause, if any Throwable ourCause = getCause(); if (ourCause != null) - ourCause.printEnclosedStackTrace(s, trace, prefix.concat(CAUSE_CAPTION), prefix, dejaVu); + ourCause.printEnclosedStackTrace(s, lineBuffer, trace, CAUSE_CAPTION, prefix, dejaVu); } } @@ -766,45 +795,6 @@ public void printStackTrace(PrintWriter s) { printStackTrace(new WrappedPrintWriter(s)); } - /** - * Use a StringBuilder to print multiple StackTraceElements - */ - private static void printStackTrace0(PrintStreamOrWriter printer, StackTraceElement[] trace) { - printStackTrace0(printer, null, trace, trace.length - 1); - } - - /** - * Use a StringBuilder to print multiple StackTraceElements - */ - private static void printStackTrace0( - PrintStreamOrWriter printer, - String prefix, - StackTraceElement[] trace, - int traceEnd) { - var sb = new StringBuilder(128); - if (prefix != null) { - sb.append(prefix); - } - sb.append("\tat "); - int prefixAndAtLength = sb.length(); - for (int i = 0; i <= traceEnd; i++) { - if (i != 0) { - sb.setLength(prefixAndAtLength); - } - printer.println(trace[i] - .appendTo(sb)); - } - - int framesInCommon = trace.length - 1 - traceEnd; - if (framesInCommon != 0) { - sb.setLength(prefix == null ? 0 : prefix.length()); - printer.println( - sb.append("\t... ") - .append(framesInCommon) - .append(" more")); - } - } - /** * Wrapper class for PrintStream and PrintWriter to enable a single * implementation of printStackTrace. From 2483992febb918a473393f935300510eb98687fa Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sat, 26 Apr 2025 14:48:50 +0800 Subject: [PATCH 13/18] add testcase --- .../java/lang/Throwable/PrintStackTrace.java | 257 ++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 test/jdk/java/lang/Throwable/PrintStackTrace.java diff --git a/test/jdk/java/lang/Throwable/PrintStackTrace.java b/test/jdk/java/lang/Throwable/PrintStackTrace.java new file mode 100644 index 0000000000000..1097e12b91482 --- /dev/null +++ b/test/jdk/java/lang/Throwable/PrintStackTrace.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Alibaba Group Holding Limited. 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. + */ + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +import org.testng.annotations.Test; +import static org.testng.Assert.*; +/* + * @test + * @bug 8355636 + * @library /test/lib + * @run testng PrintStackTrace + * @summary Verify PrintStackTrace results + */ + +public class PrintStackTrace { + + private static void fn() { + throw new RuntimeException(); + } + + private static void f9() { + fn(); + } + + private static void f8() { + f9(); + } + + private static void f7() { + f8(); + } + + private static void f6() { + f7(); + } + + private static void f5() { + f6(); + } + + private static void f4() { + f5(); + } + + private static void f3() { + f4(); + } + + private static void f2() { + f3(); + } + + private static void f1() { + f2(); + } + + private static void f0() { + f1(); + } + + + private static void yn() { + try { + f0(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void y9() { + yn(); + } + + private static void y8() { + y9(); + } + + private static void y7() { + y8(); + } + + private static void y6() { + y7(); + } + + private static void y5() { + y6(); + } + + private static void y4() { + y5(); + } + + private static void y3() { + y4(); + } + + private static void y2() { + y3(); + } + + private static void y1() { + y2(); + } + + private static void y0() { + y1(); + } + + private static void xn() { + try { + y0(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void x9() { + xn(); + } + + private static void x8() { + x9(); + } + + private static void x7() { + x8(); + } + + private static void x6() { + x7(); + } + + private static void x5() { + x6(); + } + + private static void x4() { + x5(); + } + + private static void x3() { + x4(); + } + + private static void x2() { + x3(); + } + + private static void x1() { + x2(); + } + + private static void x0() { + x1(); + } + + public static void main(String[] args) { + Exception error = null; + try { + x0(); + } catch (Exception e1) { + error = e1; + } + var byteout = new ByteArrayOutputStream(); + Charset charset = StandardCharsets.UTF_8; + PrintStream printStream = new PrintStream(byteout, true, charset); + error.printStackTrace(printStream); + + String expect = + """ + java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException + at PrintStackTrace.xn(PrintStackTrace.java:139) + at PrintStackTrace.x9(PrintStackTrace.java:144) + at PrintStackTrace.x8(PrintStackTrace.java:148) + at PrintStackTrace.x7(PrintStackTrace.java:152) + at PrintStackTrace.x6(PrintStackTrace.java:156) + at PrintStackTrace.x5(PrintStackTrace.java:160) + at PrintStackTrace.x4(PrintStackTrace.java:164) + at PrintStackTrace.x3(PrintStackTrace.java:168) + at PrintStackTrace.x2(PrintStackTrace.java:172) + at PrintStackTrace.x1(PrintStackTrace.java:176) + at PrintStackTrace.x0(PrintStackTrace.java:180) + at PrintStackTrace.main(PrintStackTrace.java:186) + Caused by: java.lang.RuntimeException: java.lang.RuntimeException + at PrintStackTrace.yn(PrintStackTrace.java:91) + at PrintStackTrace.y9(PrintStackTrace.java:96) + at PrintStackTrace.y8(PrintStackTrace.java:100) + at PrintStackTrace.y7(PrintStackTrace.java:104) + at PrintStackTrace.y6(PrintStackTrace.java:108) + at PrintStackTrace.y5(PrintStackTrace.java:112) + at PrintStackTrace.y4(PrintStackTrace.java:116) + at PrintStackTrace.y3(PrintStackTrace.java:120) + at PrintStackTrace.y2(PrintStackTrace.java:124) + at PrintStackTrace.y1(PrintStackTrace.java:128) + at PrintStackTrace.y0(PrintStackTrace.java:132) + at PrintStackTrace.xn(PrintStackTrace.java:137) + ... 11 more + Caused by: java.lang.RuntimeException + at PrintStackTrace.fn(PrintStackTrace.java:43) + at PrintStackTrace.f9(PrintStackTrace.java:47) + at PrintStackTrace.f8(PrintStackTrace.java:51) + at PrintStackTrace.f7(PrintStackTrace.java:55) + at PrintStackTrace.f6(PrintStackTrace.java:59) + at PrintStackTrace.f5(PrintStackTrace.java:63) + at PrintStackTrace.f4(PrintStackTrace.java:67) + at PrintStackTrace.f3(PrintStackTrace.java:71) + at PrintStackTrace.f2(PrintStackTrace.java:75) + at PrintStackTrace.f1(PrintStackTrace.java:79) + at PrintStackTrace.f0(PrintStackTrace.java:83) + at PrintStackTrace.yn(PrintStackTrace.java:89) + ... 22 more + """; + String s = byteout.toString(); + if (!expect.equals(s)) { + System.err.println(s); + throw new RuntimeException("stackTrace error"); + } + } + + /** + * Execute "java" with the given arguments, returning the exit code. + */ + @Test + public void exec() throws Exception { + int exitValue = jdk.test.lib.process.ProcessTools.executeTestJava("PrintStackTrace") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + assertTrue(exitValue == 0); + } +} From 3d7a921a4ebeb785c7ac685afa0a62065da7967a Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sat, 26 Apr 2025 14:57:15 +0800 Subject: [PATCH 14/18] fix code style --- .../java/lang/Throwable/PrintStackTrace.java | 85 +++++++++---------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/test/jdk/java/lang/Throwable/PrintStackTrace.java b/test/jdk/java/lang/Throwable/PrintStackTrace.java index 1097e12b91482..5c4b59dcb9473 100644 --- a/test/jdk/java/lang/Throwable/PrintStackTrace.java +++ b/test/jdk/java/lang/Throwable/PrintStackTrace.java @@ -192,50 +192,47 @@ public static void main(String[] args) { PrintStream printStream = new PrintStream(byteout, true, charset); error.printStackTrace(printStream); - String expect = - """ - java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException - at PrintStackTrace.xn(PrintStackTrace.java:139) - at PrintStackTrace.x9(PrintStackTrace.java:144) - at PrintStackTrace.x8(PrintStackTrace.java:148) - at PrintStackTrace.x7(PrintStackTrace.java:152) - at PrintStackTrace.x6(PrintStackTrace.java:156) - at PrintStackTrace.x5(PrintStackTrace.java:160) - at PrintStackTrace.x4(PrintStackTrace.java:164) - at PrintStackTrace.x3(PrintStackTrace.java:168) - at PrintStackTrace.x2(PrintStackTrace.java:172) - at PrintStackTrace.x1(PrintStackTrace.java:176) - at PrintStackTrace.x0(PrintStackTrace.java:180) - at PrintStackTrace.main(PrintStackTrace.java:186) - Caused by: java.lang.RuntimeException: java.lang.RuntimeException - at PrintStackTrace.yn(PrintStackTrace.java:91) - at PrintStackTrace.y9(PrintStackTrace.java:96) - at PrintStackTrace.y8(PrintStackTrace.java:100) - at PrintStackTrace.y7(PrintStackTrace.java:104) - at PrintStackTrace.y6(PrintStackTrace.java:108) - at PrintStackTrace.y5(PrintStackTrace.java:112) - at PrintStackTrace.y4(PrintStackTrace.java:116) - at PrintStackTrace.y3(PrintStackTrace.java:120) - at PrintStackTrace.y2(PrintStackTrace.java:124) - at PrintStackTrace.y1(PrintStackTrace.java:128) - at PrintStackTrace.y0(PrintStackTrace.java:132) - at PrintStackTrace.xn(PrintStackTrace.java:137) - ... 11 more - Caused by: java.lang.RuntimeException - at PrintStackTrace.fn(PrintStackTrace.java:43) - at PrintStackTrace.f9(PrintStackTrace.java:47) - at PrintStackTrace.f8(PrintStackTrace.java:51) - at PrintStackTrace.f7(PrintStackTrace.java:55) - at PrintStackTrace.f6(PrintStackTrace.java:59) - at PrintStackTrace.f5(PrintStackTrace.java:63) - at PrintStackTrace.f4(PrintStackTrace.java:67) - at PrintStackTrace.f3(PrintStackTrace.java:71) - at PrintStackTrace.f2(PrintStackTrace.java:75) - at PrintStackTrace.f1(PrintStackTrace.java:79) - at PrintStackTrace.f0(PrintStackTrace.java:83) - at PrintStackTrace.yn(PrintStackTrace.java:89) - ... 22 more - """; + String expect = "java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException\n" + + "\tat PrintStackTrace.xn(PrintStackTrace.java:139)\n" + + "\tat PrintStackTrace.x9(PrintStackTrace.java:144)\n" + + "\tat PrintStackTrace.x8(PrintStackTrace.java:148)\n" + + "\tat PrintStackTrace.x7(PrintStackTrace.java:152)\n" + + "\tat PrintStackTrace.x6(PrintStackTrace.java:156)\n" + + "\tat PrintStackTrace.x5(PrintStackTrace.java:160)\n" + + "\tat PrintStackTrace.x4(PrintStackTrace.java:164)\n" + + "\tat PrintStackTrace.x3(PrintStackTrace.java:168)\n" + + "\tat PrintStackTrace.x2(PrintStackTrace.java:172)\n" + + "\tat PrintStackTrace.x1(PrintStackTrace.java:176)\n" + + "\tat PrintStackTrace.x0(PrintStackTrace.java:180)\n" + + "\tat PrintStackTrace.main(PrintStackTrace.java:186)\n" + + "Caused by: java.lang.RuntimeException: java.lang.RuntimeException\n" + + "\tat PrintStackTrace.yn(PrintStackTrace.java:91)\n" + + "\tat PrintStackTrace.y9(PrintStackTrace.java:96)\n" + + "\tat PrintStackTrace.y8(PrintStackTrace.java:100)\n" + + "\tat PrintStackTrace.y7(PrintStackTrace.java:104)\n" + + "\tat PrintStackTrace.y6(PrintStackTrace.java:108)\n" + + "\tat PrintStackTrace.y5(PrintStackTrace.java:112)\n" + + "\tat PrintStackTrace.y4(PrintStackTrace.java:116)\n" + + "\tat PrintStackTrace.y3(PrintStackTrace.java:120)\n" + + "\tat PrintStackTrace.y2(PrintStackTrace.java:124)\n" + + "\tat PrintStackTrace.y1(PrintStackTrace.java:128)\n" + + "\tat PrintStackTrace.y0(PrintStackTrace.java:132)\n" + + "\tat PrintStackTrace.xn(PrintStackTrace.java:137)\n" + + "\t... 11 more\n" + + "Caused by: java.lang.RuntimeException\n" + + "\tat PrintStackTrace.fn(PrintStackTrace.java:43)\n" + + "\tat PrintStackTrace.f9(PrintStackTrace.java:47)\n" + + "\tat PrintStackTrace.f8(PrintStackTrace.java:51)\n" + + "\tat PrintStackTrace.f7(PrintStackTrace.java:55)\n" + + "\tat PrintStackTrace.f6(PrintStackTrace.java:59)\n" + + "\tat PrintStackTrace.f5(PrintStackTrace.java:63)\n" + + "\tat PrintStackTrace.f4(PrintStackTrace.java:67)\n" + + "\tat PrintStackTrace.f3(PrintStackTrace.java:71)\n" + + "\tat PrintStackTrace.f2(PrintStackTrace.java:75)\n" + + "\tat PrintStackTrace.f1(PrintStackTrace.java:79)\n" + + "\tat PrintStackTrace.f0(PrintStackTrace.java:83)\n" + + "\tat PrintStackTrace.yn(PrintStackTrace.java:89)\n" + + "\t... 22 more\n"; String s = byteout.toString(); if (!expect.equals(s)) { System.err.println(s); From e40726c1c0dfcbc284010b187e3203617afef519 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sat, 26 Apr 2025 17:07:09 +0800 Subject: [PATCH 15/18] fix benchmark, use FileOutputStream --- .../org/openjdk/bench/java/lang/Throwables.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/micro/org/openjdk/bench/java/lang/Throwables.java b/test/micro/org/openjdk/bench/java/lang/Throwables.java index 096dae9af8376..a72c7128b7e93 100644 --- a/test/micro/org/openjdk/bench/java/lang/Throwables.java +++ b/test/micro/org/openjdk/bench/java/lang/Throwables.java @@ -35,9 +35,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; +import java.io.*; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @@ -51,10 +49,12 @@ public class Throwables { @Setup public void setup() { - byteArrayOutputStream = new OutputStream() { - @Override - public void write(int b) throws IOException {} - }; + try { + File file = new File(File.createTempFile("PrintStackTrace", ".tmp").getAbsolutePath()); + byteArrayOutputStream = new FileOutputStream(file); + } catch (IOException e) { + throw new RuntimeException(e); + } } @Benchmark From d5e9e413d03ee376a0f24d23d35cbbed1a96a4ff Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sat, 26 Apr 2025 19:26:13 +0800 Subject: [PATCH 16/18] fix windows lineSeparator --- .../java/lang/Throwable/PrintStackTrace.java | 82 ++++++++++--------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/test/jdk/java/lang/Throwable/PrintStackTrace.java b/test/jdk/java/lang/Throwable/PrintStackTrace.java index 5c4b59dcb9473..53ad7821fde87 100644 --- a/test/jdk/java/lang/Throwable/PrintStackTrace.java +++ b/test/jdk/java/lang/Throwable/PrintStackTrace.java @@ -192,47 +192,49 @@ public static void main(String[] args) { PrintStream printStream = new PrintStream(byteout, true, charset); error.printStackTrace(printStream); + var lineSeparator = System.lineSeparator(); + String expect = "java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException\n" + - "\tat PrintStackTrace.xn(PrintStackTrace.java:139)\n" + - "\tat PrintStackTrace.x9(PrintStackTrace.java:144)\n" + - "\tat PrintStackTrace.x8(PrintStackTrace.java:148)\n" + - "\tat PrintStackTrace.x7(PrintStackTrace.java:152)\n" + - "\tat PrintStackTrace.x6(PrintStackTrace.java:156)\n" + - "\tat PrintStackTrace.x5(PrintStackTrace.java:160)\n" + - "\tat PrintStackTrace.x4(PrintStackTrace.java:164)\n" + - "\tat PrintStackTrace.x3(PrintStackTrace.java:168)\n" + - "\tat PrintStackTrace.x2(PrintStackTrace.java:172)\n" + - "\tat PrintStackTrace.x1(PrintStackTrace.java:176)\n" + - "\tat PrintStackTrace.x0(PrintStackTrace.java:180)\n" + - "\tat PrintStackTrace.main(PrintStackTrace.java:186)\n" + - "Caused by: java.lang.RuntimeException: java.lang.RuntimeException\n" + - "\tat PrintStackTrace.yn(PrintStackTrace.java:91)\n" + - "\tat PrintStackTrace.y9(PrintStackTrace.java:96)\n" + - "\tat PrintStackTrace.y8(PrintStackTrace.java:100)\n" + - "\tat PrintStackTrace.y7(PrintStackTrace.java:104)\n" + - "\tat PrintStackTrace.y6(PrintStackTrace.java:108)\n" + - "\tat PrintStackTrace.y5(PrintStackTrace.java:112)\n" + - "\tat PrintStackTrace.y4(PrintStackTrace.java:116)\n" + - "\tat PrintStackTrace.y3(PrintStackTrace.java:120)\n" + - "\tat PrintStackTrace.y2(PrintStackTrace.java:124)\n" + - "\tat PrintStackTrace.y1(PrintStackTrace.java:128)\n" + - "\tat PrintStackTrace.y0(PrintStackTrace.java:132)\n" + - "\tat PrintStackTrace.xn(PrintStackTrace.java:137)\n" + - "\t... 11 more\n" + - "Caused by: java.lang.RuntimeException\n" + - "\tat PrintStackTrace.fn(PrintStackTrace.java:43)\n" + - "\tat PrintStackTrace.f9(PrintStackTrace.java:47)\n" + - "\tat PrintStackTrace.f8(PrintStackTrace.java:51)\n" + - "\tat PrintStackTrace.f7(PrintStackTrace.java:55)\n" + - "\tat PrintStackTrace.f6(PrintStackTrace.java:59)\n" + - "\tat PrintStackTrace.f5(PrintStackTrace.java:63)\n" + - "\tat PrintStackTrace.f4(PrintStackTrace.java:67)\n" + - "\tat PrintStackTrace.f3(PrintStackTrace.java:71)\n" + - "\tat PrintStackTrace.f2(PrintStackTrace.java:75)\n" + - "\tat PrintStackTrace.f1(PrintStackTrace.java:79)\n" + - "\tat PrintStackTrace.f0(PrintStackTrace.java:83)\n" + - "\tat PrintStackTrace.yn(PrintStackTrace.java:89)\n" + - "\t... 22 more\n"; + "\tat PrintStackTrace.xn(PrintStackTrace.java:139)" + lineSeparator + + "\tat PrintStackTrace.x9(PrintStackTrace.java:144)" + lineSeparator + + "\tat PrintStackTrace.x8(PrintStackTrace.java:148)" + lineSeparator + + "\tat PrintStackTrace.x7(PrintStackTrace.java:152)" + lineSeparator + + "\tat PrintStackTrace.x6(PrintStackTrace.java:156)" + lineSeparator + + "\tat PrintStackTrace.x5(PrintStackTrace.java:160)" + lineSeparator + + "\tat PrintStackTrace.x4(PrintStackTrace.java:164)" + lineSeparator + + "\tat PrintStackTrace.x3(PrintStackTrace.java:168)" + lineSeparator + + "\tat PrintStackTrace.x2(PrintStackTrace.java:172)" + lineSeparator + + "\tat PrintStackTrace.x1(PrintStackTrace.java:176)" + lineSeparator + + "\tat PrintStackTrace.x0(PrintStackTrace.java:180)" + lineSeparator + + "\tat PrintStackTrace.main(PrintStackTrace.java:186)" + lineSeparator + + "Caused by: java.lang.RuntimeException: java.lang.RuntimeException" + lineSeparator + + "\tat PrintStackTrace.yn(PrintStackTrace.java:91)" + lineSeparator + + "\tat PrintStackTrace.y9(PrintStackTrace.java:96)" + lineSeparator + + "\tat PrintStackTrace.y8(PrintStackTrace.java:100)" + lineSeparator + + "\tat PrintStackTrace.y7(PrintStackTrace.java:104)" + lineSeparator + + "\tat PrintStackTrace.y6(PrintStackTrace.java:108)" + lineSeparator + + "\tat PrintStackTrace.y5(PrintStackTrace.java:112)" + lineSeparator + + "\tat PrintStackTrace.y4(PrintStackTrace.java:116)" + lineSeparator + + "\tat PrintStackTrace.y3(PrintStackTrace.java:120)" + lineSeparator + + "\tat PrintStackTrace.y2(PrintStackTrace.java:124)" + lineSeparator + + "\tat PrintStackTrace.y1(PrintStackTrace.java:128)" + lineSeparator + + "\tat PrintStackTrace.y0(PrintStackTrace.java:132)" + lineSeparator + + "\tat PrintStackTrace.xn(PrintStackTrace.java:137)" + lineSeparator + + "\t... 11 more" + lineSeparator + + "Caused by: java.lang.RuntimeException" + lineSeparator + + "\tat PrintStackTrace.fn(PrintStackTrace.java:43)" + lineSeparator + + "\tat PrintStackTrace.f9(PrintStackTrace.java:47)" + lineSeparator + + "\tat PrintStackTrace.f8(PrintStackTrace.java:51)" + lineSeparator + + "\tat PrintStackTrace.f7(PrintStackTrace.java:55)" + lineSeparator + + "\tat PrintStackTrace.f6(PrintStackTrace.java:59)" + lineSeparator + + "\tat PrintStackTrace.f5(PrintStackTrace.java:63)" + lineSeparator + + "\tat PrintStackTrace.f4(PrintStackTrace.java:67)" + lineSeparator + + "\tat PrintStackTrace.f3(PrintStackTrace.java:71)" + lineSeparator + + "\tat PrintStackTrace.f2(PrintStackTrace.java:75)" + lineSeparator + + "\tat PrintStackTrace.f1(PrintStackTrace.java:79)" + lineSeparator + + "\tat PrintStackTrace.f0(PrintStackTrace.java:83)" + lineSeparator + + "\tat PrintStackTrace.yn(PrintStackTrace.java:89)" + lineSeparator + + "\t... 22 more" + lineSeparator; String s = byteout.toString(); if (!expect.equals(s)) { System.err.println(s); From 6160f403c0f948e95ffac054fbf7910ed9899baf Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sun, 27 Apr 2025 00:10:00 +0800 Subject: [PATCH 17/18] fix windows build error --- test/jdk/java/lang/Throwable/PrintStackTrace.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/java/lang/Throwable/PrintStackTrace.java b/test/jdk/java/lang/Throwable/PrintStackTrace.java index 53ad7821fde87..192bd0bcdc258 100644 --- a/test/jdk/java/lang/Throwable/PrintStackTrace.java +++ b/test/jdk/java/lang/Throwable/PrintStackTrace.java @@ -194,7 +194,7 @@ public static void main(String[] args) { var lineSeparator = System.lineSeparator(); - String expect = "java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException\n" + + String expect = "java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException" + lineSeparator + "\tat PrintStackTrace.xn(PrintStackTrace.java:139)" + lineSeparator + "\tat PrintStackTrace.x9(PrintStackTrace.java:144)" + lineSeparator + "\tat PrintStackTrace.x8(PrintStackTrace.java:148)" + lineSeparator + From 6bbe90f6da48f158c4a8af4a7b7b54ad80407211 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Sun, 27 Apr 2025 06:39:31 +0800 Subject: [PATCH 18/18] Update src/java.base/share/classes/java/lang/Throwable.java Co-authored-by: Hendrik Schick <30866028+ky0n@users.noreply.github.com> --- src/java.base/share/classes/java/lang/Throwable.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 891863b101070..e276b3b43b7f9 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -719,7 +719,6 @@ private void printStackTrace(PrintStreamOrWriter s) { se.printEnclosedStackTrace(s, lineBuffer, trace, SUPPRESSED_CAPTION, "\t", dejaVu); // Print cause, if any - if (ourCause != null) { ourCause.printEnclosedStackTrace(s, lineBuffer, trace, CAUSE_CAPTION, "", dejaVu); }