1 /*
 2  * Copyright (c) 2023, 2024, 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 Basic test for jcmd Thread.vthread_summary
27  * @enablePreview
28  * @library /test/lib
29  * @run main/othervm VThreadSummaryTest
30  */
31 
32 import java.net.InetAddress;
33 import java.net.InetSocketAddress;
34 import java.net.ServerSocket;
35 import java.net.Socket;
36 import java.net.SocketTimeoutException;
37 import java.util.concurrent.CompletableFuture;
38 import java.util.concurrent.Executors;
39 import jdk.test.lib.dcmd.PidJcmdExecutor;
40 import jdk.test.lib.process.OutputAnalyzer;
41 
42 public class VThreadSummaryTest {
43     public static void main(String[] args) throws Exception {
44 
45         // ensure common pool is initialized
46         CompletableFuture.runAsync(() -> { });
47 
48         // ensure at least one thread pool executor and one thread-per-task executor
49         try (var pool = Executors.newFixedThreadPool(1);
50              var executor = Executors.newVirtualThreadPerTaskExecutor()) {
51 
52             // ensure poller mechanism is initialized by doing blocking I/O on a virtual thread
53             executor.submit(() -> {
54                 try (var listener = new ServerSocket()) {
55                     InetAddress lb = InetAddress.getLoopbackAddress();
56                     listener.bind(new InetSocketAddress(lb, 0));
57                     listener.setSoTimeout(1000);
58                     try {
59                         Socket s = listener.accept();
60                         throw new RuntimeException("Connection from " + s + " ???");
61                     } catch (SocketTimeoutException e) {
62                         // expected
63                     }
64                 }
65                 return null;
66             }).get();
67 
68             OutputAnalyzer output = new PidJcmdExecutor().execute("Thread.vthread_summary");
69 
70             // thread groupings
71             output.shouldContain("<root>")
72                     .shouldContain("java.util.concurrent.ThreadPoolExecutor")
73                     .shouldContain("java.util.concurrent.ThreadPerTaskExecutor")
74                     .shouldContain("ForkJoinPool.commonPool");
75 
76             // virtual thread schedulers
77             output.shouldContain("Default virtual thread scheduler:")
78                     .shouldContain("Running, parallelism")
79                     .shouldContain("Timeout schedulers:");
80 
81             // I/O pollers
82             output.shouldContain("Read I/O pollers:")
83                     .shouldContain("Write I/O pollers:");
84         }
85     }
86 }