This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.
The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.
If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:
While the JDK Mission Control client can work with many different JVMs, it is highly recommended that you use the Oracle JDK/JVM as your JVM when running the JDK Mission Control Client on the Eclipse platform. Make sure to use Oracle HotSpot JDK 7 Update 14 or later. Running on a JRE is not recommended, as this will disable the autodetection of local JVMs.
+
While the JDK Mission Control client can work with many different JVMs, it is highly recommended that you use the Oracle JDK/JVM as your JVM when running the JDK Mission Control Client on the Eclipse platform. Make sure to use Oracle HotSpot JDK 21 or later. Running on a JRE is not recommended, as this will disable the autodetection of local JVMs.
To change the JVM on which you run Eclipse:
@@ -60,9 +60,9 @@
Changing Your JVM
On the third line down (after org.eclipse.platform), add the following:
-vm <Full path JAVA_HOME/jre/bin/ folder>
The full path might look like this on Windows:
-
C:\Program Files\Java\jdk1.7.0\jre\bin\
+
C:\Program Files\Java\jdk21\jre\bin\
Or, the path might look like this on Linux and Solaris:
-
$HOME/jdk1.7.0/jre/bin/
+
$HOME/jdk21/jre/bin/
Depending upon your particular JVM implementation and the applications running on it, you can set any valid JVM command-line option.
diff --git a/application/org.openjdk.jmc.rcp.application/plugin.xml b/application/org.openjdk.jmc.rcp.application/plugin.xml
index d3ecf8db1..e577d50d4 100644
--- a/application/org.openjdk.jmc.rcp.application/plugin.xml
+++ b/application/org.openjdk.jmc.rcp.application/plugin.xml
@@ -1,6 +1,6 @@
-
+
Welcome to JDK Mission Control
diff --git a/application/org.openjdk.jmc.rcp.intro/content/console_samples_l.xhtml b/application/org.openjdk.jmc.rcp.intro/content/console_samples_l.xhtml
index 2887cfd4b..3fa957ef6 100644
--- a/application/org.openjdk.jmc.rcp.intro/content/console_samples_l.xhtml
+++ b/application/org.openjdk.jmc.rcp.intro/content/console_samples_l.xhtml
@@ -1,10 +1,10 @@
-
+
Welcome to JDK Mission Control
diff --git a/application/org.openjdk.jmc.rcp.intro/content/jfr_samples.xhtml b/application/org.openjdk.jmc.rcp.intro/content/jfr_samples.xhtml
index 0c04e5ad8..da1febfed 100644
--- a/application/org.openjdk.jmc.rcp.intro/content/jfr_samples.xhtml
+++ b/application/org.openjdk.jmc.rcp.intro/content/jfr_samples.xhtml
@@ -1,10 +1,10 @@
-
+
Welcome to JDK Mission Control
diff --git a/application/org.openjdk.jmc.rcp.intro/content/jfr_samples_l.xhtml b/application/org.openjdk.jmc.rcp.intro/content/jfr_samples_l.xhtml
index 5f24b83d5..55404d3ba 100644
--- a/application/org.openjdk.jmc.rcp.intro/content/jfr_samples_l.xhtml
+++ b/application/org.openjdk.jmc.rcp.intro/content/jfr_samples_l.xhtml
@@ -1,10 +1,10 @@
-
+
Welcome to JDK Mission Control
diff --git a/application/org.openjdk.jmc.rcp.intro/content/plugins_samples.xhtml b/application/org.openjdk.jmc.rcp.intro/content/plugins_samples.xhtml
index 69c30625b..4837d20f7 100644
--- a/application/org.openjdk.jmc.rcp.intro/content/plugins_samples.xhtml
+++ b/application/org.openjdk.jmc.rcp.intro/content/plugins_samples.xhtml
@@ -1,10 +1,10 @@
-
+
Welcome to JDK Mission Control
diff --git a/application/org.openjdk.jmc.rcp.intro/content/plugins_samples_l.xhtml b/application/org.openjdk.jmc.rcp.intro/content/plugins_samples_l.xhtml
index 883fdc076..2c578fb72 100644
--- a/application/org.openjdk.jmc.rcp.intro/content/plugins_samples_l.xhtml
+++ b/application/org.openjdk.jmc.rcp.intro/content/plugins_samples_l.xhtml
@@ -1,10 +1,10 @@
-
+
Welcome to JDK Mission Control
diff --git a/application/org.openjdk.jmc.rcp.intro/content/root.xhtml b/application/org.openjdk.jmc.rcp.intro/content/root.xhtml
index 3bd35b3a7..57fd7681c 100644
--- a/application/org.openjdk.jmc.rcp.intro/content/root.xhtml
+++ b/application/org.openjdk.jmc.rcp.intro/content/root.xhtml
@@ -1,10 +1,10 @@
-
+
Welcome to JDK Mission Control
diff --git a/application/org.openjdk.jmc.rcp.intro/content/root_l.xhtml b/application/org.openjdk.jmc.rcp.intro/content/root_l.xhtml
index 21620945c..b035fa55d 100644
--- a/application/org.openjdk.jmc.rcp.intro/content/root_l.xhtml
+++ b/application/org.openjdk.jmc.rcp.intro/content/root_l.xhtml
@@ -1,10 +1,10 @@
-
+
Welcome to JDK Mission Control
diff --git a/application/org.openjdk.jmc.rcp.intro/content/standby.xhtml b/application/org.openjdk.jmc.rcp.intro/content/standby.xhtml
index 91141b94d..f8c0982fc 100644
--- a/application/org.openjdk.jmc.rcp.intro/content/standby.xhtml
+++ b/application/org.openjdk.jmc.rcp.intro/content/standby.xhtml
@@ -1,10 +1,10 @@
-
+
Welcome to JDK Mission Control
diff --git a/application/org.openjdk.jmc.updatesite.ide/src/main/resources/index.html b/application/org.openjdk.jmc.updatesite.ide/src/main/resources/index.html
index d0a8489cb..78f8e64be 100644
--- a/application/org.openjdk.jmc.updatesite.ide/src/main/resources/index.html
+++ b/application/org.openjdk.jmc.updatesite.ide/src/main/resources/index.html
@@ -1,7 +1,7 @@
@@ -38,7 +38,7 @@
This update site provides a set of plug-ins for the Eclipse IDE designed to help develop, profile
- and diagnose applications running on the Oracle® Java HotSpot VM, and (as of JDK 11) OpenJDK.
+ and diagnose applications running on the Oracle® Java HotSpot VM, and OpenJDK.
JDK Mission Control includes tools to monitor, manage and profile your Java application without
introducing the performance overhead normally associated with tools of this type. JDK Mission Control's low performance overhead
@@ -71,9 +71,9 @@
Requirements
-
Requires Eclipse 4.31.
+
Requires Eclipse 4.34.
Requires any previously installed versions of JMC 4.x, 5.x, 6.x or 7.x to be uninstalled before installing JMC 9.
-
Note that you need to run your Eclipse on a JDK (version 11 or above) installation for all features to work. For more information on this,
+
Note that you need to run your Eclipse on a JDK (version 21 or above) installation for all features to work. For more information on this,
please see the Run Eclipse on JDK HOWTO.
@@ -108,7 +108,7 @@
Prerequisites
- JDK Mission Control is a set of plug-ins for Eclipse 4.31.
+ JDK Mission Control is a set of plug-ins for Eclipse 4.34.
diff --git a/application/uitests/org.openjdk.jmc.test.jemmy/src/main/java/org/openjdk/jmc/test/jemmy/misc/wrappers/JvmBrowser.java b/application/uitests/org.openjdk.jmc.test.jemmy/src/main/java/org/openjdk/jmc/test/jemmy/misc/wrappers/JvmBrowser.java
index 5dc501bbe..d400f3d2d 100644
--- a/application/uitests/org.openjdk.jmc.test.jemmy/src/main/java/org/openjdk/jmc/test/jemmy/misc/wrappers/JvmBrowser.java
+++ b/application/uitests/org.openjdk.jmc.test.jemmy/src/main/java/org/openjdk/jmc/test/jemmy/misc/wrappers/JvmBrowser.java
@@ -41,6 +41,7 @@
import java.util.List;
import java.util.stream.Collectors;
+import org.jemmy.JemmyException;
import org.jemmy.TimeoutExpiredException;
import org.junit.Assert;
@@ -365,7 +366,18 @@ public void disconnect() {
* the name of the connection
*/
public void disconnect(String ... path) {
- selectContextOption(ACTION_DISCONNECT_TEXT, path);
+ int maxRetries = 5;
+ for (int i = 0; i < maxRetries; i++) {
+ try {
+ selectContextOption(ACTION_DISCONNECT_TEXT, path);
+ break;
+ } catch (JemmyException e) {
+ if (i == maxRetries - 1) {
+ throw e;
+ }
+ sleep(1000);
+ }
+ }
MCDialog disconnectDialog = new MCDialog(ACTION_DISCONNECT_TEXT);
disconnectDialog.clickButton(MCButton.Labels.OK);
}
diff --git a/core/license/THIRD_PARTY_LICENSES.txt b/core/license/THIRD_PARTY_LICENSES.txt
index af3ffa0a0..f82cfe073 100644
--- a/core/license/THIRD_PARTY_LICENSES.txt
+++ b/core/license/THIRD_PARTY_LICENSES.txt
@@ -10,7 +10,7 @@ in this project:
===============================================================================
-## org.owasp.encoder:encoder@1.2.2 (BSD-3-Clause)
+## org.owasp.encoder:encoder@1.4.0 (BSD-3-Clause)
Copyright (c) 2015 Jeff Ichnowski
All rights reserved.
@@ -19,19 +19,19 @@ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the following
-disclaimer.
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following
-disclaimer in the documentation and/or other materials
-provided with the distribution.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
-* Neither the name of the OWASP nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior written
-permission.
+ * Neither the name of the OWASP nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -47,9 +47,9 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
===============================================================================
-## at.yawk.lz4:lz4-java@1.10.2 (Apache-2.0)
+## at.yawk.lz4:lz4-java@1.10.4 (Apache-2.0)
- URL for License – http://opensource.org/licenses/Apache-2.0
+URL for License – http://opensource.org/licenses/Apache-2.0
Apache License
Version 2.0, January 2004
diff --git a/core/org.openjdk.jmc.common/pom.xml b/core/org.openjdk.jmc.common/pom.xml
index 157589e1f..5a266018d 100644
--- a/core/org.openjdk.jmc.common/pom.xml
+++ b/core/org.openjdk.jmc.common/pom.xml
@@ -46,12 +46,12 @@
org.owasp.encoderencoder
- 1.2.3
+ 1.4.0at.yawk.lz4lz4-java
- 1.10.2
+ 1.10.4
diff --git a/core/org.openjdk.jmc.common/src/main/java/org/openjdk/jmc/common/IMCFrame.java b/core/org.openjdk.jmc.common/src/main/java/org/openjdk/jmc/common/IMCFrame.java
index 7e577e4ce..e2566f9dd 100644
--- a/core/org.openjdk.jmc.common/src/main/java/org/openjdk/jmc/common/IMCFrame.java
+++ b/core/org.openjdk.jmc.common/src/main/java/org/openjdk/jmc/common/IMCFrame.java
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2022, 2025, Datadog, Inc. All rights reserved.
+ * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2026, Datadog, Inc. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -89,7 +89,7 @@ final class Type {
/**
* The frame compilation type is unknown.
*/
- public static final Type UNKNOWN = new Type("UNKNONW"); //$NON-NLS-1$
+ public static final Type UNKNOWN = new Type("UNKNOWN"); //$NON-NLS-1$
private static final String MSG_PREFIX = "IMCFrame_Type_";
diff --git a/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/AggregatableFrame.java b/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/AggregatableFrame.java
index 10dd2b890..ea5eda031 100644
--- a/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/AggregatableFrame.java
+++ b/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/AggregatableFrame.java
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2019, 2025, Datadog, Inc. All rights reserved.
+ * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2026, Datadog, Inc. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -37,6 +37,7 @@
import org.openjdk.jmc.common.IMCMethod;
import org.openjdk.jmc.common.util.FormatToolkit;
import org.openjdk.jmc.flightrecorder.stacktrace.FrameSeparator;
+import org.openjdk.jmc.flightrecorder.stacktrace.Messages;
/**
* Frame wrapper taking into account a frame separator for hash code and equals.
@@ -135,4 +136,19 @@ public String getHumanReadableSeparatorSensitiveString() {
public String getHumanReadableShortString() {
return FormatToolkit.getHumanReadable(getMethod(), false, false, true, false, true, false);
}
+
+ /**
+ * Returns a unique key for this frame based on the fully qualified class name and method name.
+ * This key can be used for merging frames from different stack traces.
+ *
+ * @return a key in the format "fully.qualified.ClassName::methodName", or a sentinel value for
+ * special frames (root or unclassifiable frames from truncated stacks)
+ */
+ public String getMethodKey() {
+ IMCMethod method = frame.getMethod();
+ if (method == null || method.getType() == null) {
+ return Messages.getString(Messages.STACKTRACE_UNCLASSIFIABLE_FRAME);
+ }
+ return method.getType().getFullName() + "::" + method.getMethodName();
+ }
}
diff --git a/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/Node.java b/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/Node.java
index 0356b2242..905979207 100644
--- a/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/Node.java
+++ b/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/Node.java
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2021, 2025, Datadog, Inc. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Datadog, Inc. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -123,6 +123,26 @@ public boolean isLeaf() {
return children.isEmpty();
}
+ public void setWeight(double weight) {
+ this.weight = weight;
+ }
+
+ public void setCumulativeWeight(double cumulativeWeight) {
+ this.cumulativeWeight = cumulativeWeight;
+ }
+
+ public void addWeight(double delta) {
+ this.weight += delta;
+ }
+
+ public void addCumulativeWeight(double delta) {
+ this.cumulativeWeight += delta;
+ }
+
+ public void addChild(Node child) {
+ this.children.add(child);
+ }
+
@Override
public int hashCode() {
// This will get a few extra collisions.
diff --git a/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/StacktraceTreeModel.java b/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/StacktraceTreeModel.java
index a32d6078c..d41483ef6 100644
--- a/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/StacktraceTreeModel.java
+++ b/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/stacktrace/tree/StacktraceTreeModel.java
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2021, 2025, Datadog, Inc. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Datadog, Inc. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -37,6 +37,7 @@
import java.util.function.BooleanSupplier;
import org.openjdk.jmc.common.IMCFrame;
+import org.openjdk.jmc.common.IMCMethod;
import org.openjdk.jmc.common.IMCStackTrace;
import org.openjdk.jmc.common.item.IAttribute;
import org.openjdk.jmc.common.item.IItem;
@@ -272,4 +273,126 @@ private Node getOrCreateNode(Node parent, AggregatableFrame frame) {
private static IMemberAccessor getAccessor(IItemIterable iterable, IAttribute attr) {
return (attr != null) ? iterable.getType().getAccessor(attr.getKey()) : null;
}
+
+ /**
+ * Extracts a merged tree of successors (callees) for a given method. This finds all occurrences
+ * of the specified method in the tree and merges their subtrees into a single tree rooted at
+ * the method.
+ *
+ * @param typeName
+ * the fully qualified class name of the method
+ * @param methodName
+ * the method name
+ * @return a new Node representing the merged successor tree, or null if the method is not found
+ */
+ public Node extractSuccessorsFor(String typeName, String methodName) {
+ AggregatableFrame pivotFrame = findFirstMatchingFrame(root, typeName, methodName);
+ if (pivotFrame == null) {
+ return null;
+ }
+ Node result = Node.newRootNode(pivotFrame);
+ traverseForSuccessors(root, typeName, methodName, result);
+ return result.getCumulativeWeight() > 0 ? result : null;
+ }
+
+ private boolean matchesMethod(Node node, String typeName, String methodName) {
+ IMCMethod method = node.getFrame().getMethod();
+ return method != null && methodName.equals(method.getMethodName())
+ && typeName.equals(method.getType().getFullName());
+ }
+
+ private AggregatableFrame findFirstMatchingFrame(Node current, String typeName, String methodName) {
+ if (matchesMethod(current, typeName, methodName)) {
+ return current.getFrame();
+ }
+ for (Node child : current.getChildren()) {
+ AggregatableFrame found = findFirstMatchingFrame(child, typeName, methodName);
+ if (found != null) {
+ return found;
+ }
+ }
+ return null;
+ }
+
+ private void traverseForSuccessors(Node current, String typeName, String methodName, Node result) {
+ if (matchesMethod(current, typeName, methodName)) {
+ mergeSuccessorNode(result, current);
+ }
+ for (Node child : current.getChildren()) {
+ traverseForSuccessors(child, typeName, methodName, result);
+ }
+ }
+
+ private void mergeSuccessorNode(Node destNode, Node srcNode) {
+ destNode.addCumulativeWeight(srcNode.getCumulativeWeight());
+ for (Node child : srcNode.getChildren()) {
+ String key = child.getFrame().getMethodKey();
+ Node existing = findChildByKey(destNode, key);
+ if (existing == null) {
+ Node newChild = new Node(destNode, child.getFrame());
+ destNode.addChild(newChild);
+ mergeSuccessorNode(newChild, child);
+ } else {
+ mergeSuccessorNode(existing, child);
+ }
+ }
+ }
+
+ private Node findChildByKey(Node parent, String key) {
+ for (Node child : parent.getChildren()) {
+ if (child.getFrame().getMethodKey().equals(key)) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Extracts a merged tree of predecessors (callers) for a given method. This finds all
+ * occurrences of the specified method in the tree and merges their ancestor chains into a
+ * single inverted tree rooted at the method.
+ *
+ * @param typeName
+ * the fully qualified class name of the method
+ * @param methodName
+ * the method name
+ * @return a new Node representing the merged predecessor tree, or null if the method is not
+ * found
+ */
+ public Node extractPredecessorsFor(String typeName, String methodName) {
+ AggregatableFrame pivotFrame = findFirstMatchingFrame(root, typeName, methodName);
+ if (pivotFrame == null) {
+ return null;
+ }
+ Node result = Node.newRootNode(pivotFrame);
+ traverseForPredecessors(root, typeName, methodName, result);
+ return result.getCumulativeWeight() > 0 ? result : null;
+ }
+
+ private void traverseForPredecessors(Node current, String typeName, String methodName, Node result) {
+ if (matchesMethod(current, typeName, methodName)) {
+ result.addCumulativeWeight(current.getCumulativeWeight());
+ mergePredecessorChain(result, current.getParent(), current.getCumulativeWeight());
+ }
+ for (Node child : current.getChildren()) {
+ traverseForPredecessors(child, typeName, methodName, result);
+ }
+ }
+
+ private void mergePredecessorChain(Node destNode, Node srcAncestor, double weight) {
+ if (srcAncestor == null || srcAncestor.isRoot()) {
+ return;
+ }
+ String key = srcAncestor.getFrame().getMethodKey();
+ Node existing = findChildByKey(destNode, key);
+ if (existing == null) {
+ Node newChild = new Node(destNode, srcAncestor.getFrame());
+ newChild.addCumulativeWeight(weight);
+ destNode.addChild(newChild);
+ mergePredecessorChain(newChild, srcAncestor.getParent(), weight);
+ } else {
+ existing.addCumulativeWeight(weight);
+ mergePredecessorChain(existing, srcAncestor.getParent(), weight);
+ }
+ }
}
diff --git a/core/pom.xml b/core/pom.xml
index 92b2d74df..f4f78f10b 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -1,6 +1,6 @@