1 /*
 2  * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
 3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 4  *
 5  * This code is free software; you can redistribute it and/or modify it
 6  * under the terms of the GNU General Public License version 2 only, as
 7  * published by the Free Software Foundation.
 8  *
 9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /**
25  * @test
26  * @summary Test stack traces in exceptions and stack frames walked by the StackWalker
27  *     API do not include the carrier stack frames
28  * @requires vm.continuations
29  * @modules java.management
30  * @library /test/lib
31  * @run junit StackTraces
32  * @run junit/othervm -XX:+UnlockDiagnosticVMOptions -XX:+ShowCarrierFrames StackTraces
33  */
34 
35 import java.lang.management.ManagementFactory;
36 import java.util.Arrays;
37 import java.util.Set;
38 import java.util.concurrent.ForkJoinPool;
39 import static java.lang.StackWalker.Option.*;
40 
41 import jdk.test.lib.thread.VThreadRunner;
42 import org.junit.jupiter.api.Test;
43 import static org.junit.jupiter.api.Assertions.*;
44 
45 class StackTraces {
46 
47     /**
48      * Test that the stack trace in exceptions does not include the carrier thread
49      * frames, except when running with -XX:+ShowCarrierFrames.
50      */
51     @Test
52     void testStackTrace() throws Exception {
53         VThreadRunner.run(() -> {
54             Exception e = new Exception();
55             boolean found = Arrays.stream(e.getStackTrace())
56                     .map(StackTraceElement::getClassName)
57                     .anyMatch("java.util.concurrent.ForkJoinPool"::equals);
58             assertTrue(found == hasJvmArgument("-XX:+ShowCarrierFrames"));
59         });
60     }
61 
62     /**
63      * Test that StackWalker does not include carrier thread frames.
64      */
65     @Test
66     void testStackWalker() throws Exception {
67         VThreadRunner.run(() -> {
68             StackWalker walker = StackWalker.getInstance(Set.of(RETAIN_CLASS_REFERENCE));
69             boolean found = walker.walk(sf ->
70                     sf.map(StackWalker.StackFrame::getDeclaringClass)
71                             .anyMatch(c -> c == ForkJoinPool.class));
72             assertFalse(found);
73         });
74     }
75 
76     private static boolean hasJvmArgument(String arg) {
77         for (String argument : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
78             if (argument.equals(arg)) return true;
79         }
80         return false;
81     }
82 }