diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/SourceLauncher.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/SourceLauncher.java index ffb47504f24..4d679403ee7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/SourceLauncher.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/SourceLauncher.java @@ -259,13 +259,19 @@ public final class SourceLauncher { } } catch (IllegalAccessException e) { throw new Fault(Errors.CantAccessMainMethod(mainClassName)); - } catch (InvocationTargetException e) { + } catch (InvocationTargetException exception) { // remove stack frames for source launcher - int invocationFrames = e.getStackTrace().length; - Throwable target = e.getCause(); - StackTraceElement[] targetTrace = target.getStackTrace(); - target.setStackTrace(Arrays.copyOfRange(targetTrace, 0, targetTrace.length - invocationFrames)); - throw e; + StackTraceElement[] invocationElements = exception.getStackTrace(); + if (invocationElements == null) throw exception; + Throwable cause = exception.getCause(); + if (cause == null) throw exception; + StackTraceElement[] causeElements = cause.getStackTrace(); + if (causeElements == null) throw exception; + int range = causeElements.length - invocationElements.length; + if (range >= 0) { + cause.setStackTrace(Arrays.copyOfRange(causeElements, 0, range)); + } + throw exception; } return mainClass; diff --git a/test/langtools/tools/javac/launcher/SourceLauncherTest.java b/test/langtools/tools/javac/launcher/SourceLauncherTest.java index 017abb74456..0f321b0b64c 100644 --- a/test/langtools/tools/javac/launcher/SourceLauncherTest.java +++ b/test/langtools/tools/javac/launcher/SourceLauncherTest.java @@ -24,6 +24,7 @@ /* * @test * @bug 8192920 8204588 8246774 8248843 8268869 8235876 8328339 8335896 8344706 + * 8362237 * @summary Test source launcher * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -714,6 +715,42 @@ public class SourceLauncherTest extends TestRunner { "at Thrower.main(Thrower.java:4)"); } + /* + * Tests in which main throws an exception without a stacktrace. + */ + @Test + public void testTargetException2(Path base) throws IOException { + tb.writeJavaFiles(base, """ + public class TestLauncher { + public static TestLauncher testCheckcast(Object arg) { + return (TestLauncher)arg; + } + + public static void main(String[] args) { + // Warmup to trigger C2 compilation + TestLauncher t = new TestLauncher(); + for (int i = 0; i < 10_000; ++i) { + testCheckcast(t); + try { + testCheckcast(42); + } catch (Exception e) { + // Expected + } + } + // This will throw a ClassCastException without + // a stack trace if OmitStackTraceInFastThrow + // is enabled (default) + testCheckcast(42); + } + } + """); + Path file = base.resolve("TestLauncher.java"); + Result r = run(file, Collections.emptyList(), List.of("3")); + checkEmpty("stdout", r.stdOut); + checkEmpty("stderr", r.stdErr); + checkTrace("exception", r.exception, "java.lang.ClassCastException"); + } + @Test public void testNoDuplicateIncubatorWarning(Path base) throws Exception { Path module = base.resolve("lib");