Skip to content

8356870: HotSpotDiagnosticMXBean.dumpThreads and jcmd Thread.dump_to_file updates #25429

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: pr/25425
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
586 changes: 418 additions & 168 deletions src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 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
Expand Down Expand Up @@ -116,6 +116,13 @@ public interface HotSpotDiagnosticMXBean extends PlatformManagedObject {
* {@code outputFile} parameter must be an absolute path to a file that
* does not exist.
*
* <p> When the format is specified as {@link ThreadDumpFormat#JSON JSON}, the
* thread dump is generated in JavaScript Object Notation.
* <a href="doc-files/threadDump.schema.json">threadDump.schema.json</a>
* describes the thread dump format in draft
* <a href="https://tools.ietf.org/html/draft-json-schema-language-02">
* JSON Schema Language version 2</a>.
*
* <p> The thread dump will include output for all platform threads. It may
* include output for some or all virtual threads.
*
Expand Down Expand Up @@ -151,6 +158,7 @@ public static enum ThreadDumpFormat {
TEXT_PLAIN,
/**
* JSON (JavaScript Object Notation) format.
* @spec https://datatracker.ietf.org/doc/html/rfc8259 JavaScript Object Notation
*/
JSON,
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
{
"type": "object",
"properties": {
"threadDump": {
"type": "object",
"properties": {
"processId": {
"type": "string",
"description": "The native process id of the Java virtual machine."
},
"time": {
"type": "string",
"description": "The time in ISO 8601 format when the thread dump was generated."
},
"runtimeVersion": {
"type": "string",
"description": "The runtime version, see java.lang.Runtime.Version"
},
"threadContainers": {
"type": "array",
"description": "The array of thread containers (thread groupings).",
"items": [
{
"type": "object",
"properties": {
"container": {
"type": "string",
"description": "The container name. The container name is unique."
},
"parent": {
"type": [
"string",
"null"
],
"description": "The parent container name or null for the root container."
},
"owner": {
"type": [
"string",
"null"
],
"description": "The thread identifier of the owner thread if owned."
},
"threads": {
"type": "array",
"description": "The array of threads in the thread container.",
"items": [
{
"type": "object",
"properties": {
"tid": {
"type": "string",
"description": "The thread identifier."
},
"time": {
"type": "string",
"description": "The time in ISO 8601 format that the thread was sampled."
},
"name": {
"type": "string",
"description": "The thread name."
},
"state": {
"type": "string",
"description": "The thread state (Thread::getState)."
},
"virtual" : {
"type": "boolean",
"description": "true for a virtual thread."
},
"parkBlocker": {
"type": [
"object"
],
"properties": {
"object": {
"type": "string",
"description": "The blocker object responsible for the thread parking."
},
"exclusiveOwnerThreadId": {
"type": "string",
"description": "The thread identifier of the owner when the blocker object has an owner."
}
},
"required": [
"object"
]
},
"blockedOn": {
"type": "string",
"description": "The object that the thread is blocked on waiting to enter/re-enter a synchronization block/method."
},
"waitingOn": {
"type": "string",
"description": "The object that the thread is waiting to be notified (Object.wait)."
},
"stack": {
"type": "array",
"description": "The thread stack. The first element is the top of the stack.",
"items": [
{
"type": "string",
"description": "A stack trace element (java.lang.StackTraceElement)."
}
]
},
"monitorsOwned": {
"type": "array",
"description": "The objects for which monitors are owned by the thread.",
"items": {
"type": "object",
"properties": {
"depth": {
"type": "integer",
"description": "The stack depth at which the monitors are owned."
},
"locks": {
"type": "array",
"items": {
"type": [
"string",
null
],
"description": "The object for which the monitor is owned by the thread, null if eliminated"
}
}
},
"required": [
"depth",
"locks"
]
}
},
"carrier": {
"type": "string",
"description": "The thread identifier of the carrier thread if mounted."
}
},
"required": [
"tid",
"time",
"name",
"state",
"stack"
]
}
]
},
"threadCount": {
"type": "string",
"description": "The number of threads in the thread container."
}
},
"required": [
"container",
"parent",
"owner",
"threads"
]
}
]
}
},
"required": [
"processId",
"time",
"runtimeVersion",
"threadContainers"
]
}
},
"required": [
"threadDump"
]
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 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
Expand Down Expand Up @@ -153,7 +153,7 @@ public void dumpThreads(String outputFile, ThreadDumpFormat format) throws IOExc
throw new IllegalArgumentException("'outputFile' not absolute path");

try (OutputStream out = Files.newOutputStream(file, StandardOpenOption.CREATE_NEW)) {
dumpThreads(out, format);
dumpThreads(out, format);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 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
Expand All @@ -25,6 +25,7 @@
* @test
* @bug 8284161 8287008
* @summary Basic test for jcmd Thread.dump_to_file
* @modules jdk.jcmd
* @library /test/lib
* @run junit/othervm ThreadDumpToFileTest
*/
Expand Down Expand Up @@ -66,7 +67,8 @@ void testPlainThreadDump() throws IOException {
@Test
void testJsonThreadDump() throws IOException {
Path file = genThreadDumpPath(".json");
jcmdThreadDumpToFile(file, "-format=json").shouldMatch("Created");
jcmdThreadDumpToFile(file, "-format=json")
.shouldMatch("Created");

// parse the JSON text
String jsonText = Files.readString(file);
Expand All @@ -89,7 +91,8 @@ void testDoNotOverwriteFile() throws IOException {
Path file = genThreadDumpPath(".txt");
Files.writeString(file, "xxx");

jcmdThreadDumpToFile(file, "").shouldMatch("exists");
jcmdThreadDumpToFile(file, "")
.shouldMatch("exists");

// file should not be overridden
assertEquals("xxx", Files.readString(file));
Expand All @@ -102,7 +105,23 @@ void testDoNotOverwriteFile() throws IOException {
void testOverwriteFile() throws IOException {
Path file = genThreadDumpPath(".txt");
Files.writeString(file, "xxx");
jcmdThreadDumpToFile(file, "-overwrite");
jcmdThreadDumpToFile(file, "-overwrite")
.shouldMatch("Created");
}

/**
* Test output file cannot be created.
*/
@Test
void testFileCreateFails() throws IOException {
Path badFile = Path.of(".").toAbsolutePath()
.resolve("does-not-exist")
.resolve("does-not-exist")
.resolve("threads.bad");
jcmdThreadDumpToFile(badFile, "-format=plain")
.shouldMatch("Failed");
jcmdThreadDumpToFile(badFile, "-format=json")
.shouldMatch("Failed");
}

/**
Expand Down
Loading