diff --git a/agent/pom.xml b/agent/pom.xml index 77ebd9f7a..3177a8461 100644 --- a/agent/pom.xml +++ b/agent/pom.xml @@ -1,6 +1,6 @@ - 9.8 + 9.9.1 4.13.2 diff --git a/application/org.openjdk.jmc.console.jconsole/src/main/java/org/openjdk/jmc/console/jconsole/tabs/JConsolePluginTabbedPane.java b/application/org.openjdk.jmc.console.jconsole/src/main/java/org/openjdk/jmc/console/jconsole/tabs/JConsolePluginTabbedPane.java index 4a6cdd6fe..7527b4324 100644 --- a/application/org.openjdk.jmc.console.jconsole/src/main/java/org/openjdk/jmc/console/jconsole/tabs/JConsolePluginTabbedPane.java +++ b/application/org.openjdk.jmc.console.jconsole/src/main/java/org/openjdk/jmc/console/jconsole/tabs/JConsolePluginTabbedPane.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -34,9 +34,14 @@ import java.awt.BorderLayout; import java.awt.Color; +import java.awt.KeyboardFocusManager; +import java.awt.event.InputEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -45,6 +50,7 @@ import java.util.TimerTask; import java.util.logging.Level; +import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTabbedPane; @@ -52,6 +58,11 @@ import javax.swing.SwingWorker; import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; import org.openjdk.jmc.console.jconsole.Activator; import org.openjdk.jmc.console.jconsole.JConsolePluginLoader; import org.openjdk.jmc.console.jconsole.MissionControlContext; @@ -71,6 +82,7 @@ public class JConsolePluginTabbedPane extends JTabbedPane { private final Map> swingWorkers = new HashMap<>(); private volatile boolean disposeTimerTask; private final MissionControlContext ctx; + private static final String STACKTRACE_VIEW_ID = "org.openjdk.jmc.flightrecorder.ui.StacktraceView"; public JConsolePluginTabbedPane(IConnectionHandle connectionHandle) { // FIXME: Make placement configurable in settings @@ -142,6 +154,78 @@ private void addErrorTab(String title, String message) { Activator.getLogger().log(Level.WARNING, NLS.bind(Messages.JConsolePluginTabbedPane_ERROR_MESSAGE_COULD_NOT_CREATE_PLUGIN_TAB, message)); this.add(title, p); + setFocusTraversalProperties(p); + addKeyListener(p); + addKeyListenerForFwdFocusToSWT(p); + } + + /** + * Adding key listener to transfer focus forward or backward based on 'TAB' or 'Shift + TAB' + */ + private void addKeyListener(JComponent comp) { + comp.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_TAB) { + if ((e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) != 0) { + e.getComponent().transferFocusBackward(); + } else { + e.getComponent().transferFocus(); + } + e.consume(); + } + } + }); + } + + /** + * Setting the focus traversal properties. + */ + private void setFocusTraversalProperties(JComponent comp) { + comp.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.emptySet()); + comp.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, Collections.emptySet()); + comp.setFocusable(true); + comp.setFocusTraversalKeysEnabled(true); + } + + /** + * Adding key listener and checking if all the swing components are already cycled (Fwd) once. + * On completion of swing component cycle transferring focus back to SWT. + */ + private void addKeyListenerForFwdFocusToSWT(JComponent comp) { + comp.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_TAB) { + if ((e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) != 0) { + e.getComponent().transferFocusBackward(); + } else { + setFocusBackToSWT(); + } + e.consume(); + } + } + }); + } + + /** + * This method sets the focus from swing to SWT. If outline page is active focus will be set to + * outline view else to JVM Browser + */ + private void setFocusBackToSWT() { + Display.getDefault().syncExec(new Runnable() { + public void run() { + IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + try { + IViewPart outlineView = activePage.showView(STACKTRACE_VIEW_ID); + if (activePage.getActiveEditor() != null) { + outlineView.setFocus(); + } + } catch (PartInitException e) { + Activator.getLogger().log(Level.INFO, "Failed to set focus", e); //$NON-NLS-1$ + } + } + }); } private void startUpdateThread() { diff --git a/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/butterfly.png b/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/butterfly.png new file mode 100644 index 000000000..5ba2b44d4 Binary files /dev/null and b/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/butterfly.png differ diff --git a/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/butterfly@2x.png b/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/butterfly@2x.png new file mode 100644 index 000000000..e80a6b5b9 Binary files /dev/null and b/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/butterfly@2x.png differ diff --git a/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/pin.png b/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/pin.png new file mode 100644 index 000000000..8cca5e0f6 Binary files /dev/null and b/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/pin.png differ diff --git a/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/pin@2x.png b/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/pin@2x.png new file mode 100644 index 000000000..2dc1316d1 Binary files /dev/null and b/application/org.openjdk.jmc.flightrecorder.flamegraph/icons/pin@2x.png differ diff --git a/application/org.openjdk.jmc.flightrecorder.flamegraph/plugin.properties b/application/org.openjdk.jmc.flightrecorder.flamegraph/plugin.properties index 9e9ce98ee..b9fb98f48 100644 --- a/application/org.openjdk.jmc.flightrecorder.flamegraph/plugin.properties +++ b/application/org.openjdk.jmc.flightrecorder.flamegraph/plugin.properties @@ -1,6 +1,6 @@ # -# Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. -# Copyright (c) 2023, 2025, Datadog, Inc. All rights reserved. +# Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2023, 2026, Datadog, Inc. All rights reserved. # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # @@ -32,3 +32,4 @@ # WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # FLAME_GRAPH_VIEW_NAME=Flame Graph +BUTTERFLY_VIEW_NAME=Butterfly diff --git a/application/org.openjdk.jmc.flightrecorder.flamegraph/plugin.xml b/application/org.openjdk.jmc.flightrecorder.flamegraph/plugin.xml index e3acbc2e7..3e3915ef2 100644 --- a/application/org.openjdk.jmc.flightrecorder.flamegraph/plugin.xml +++ b/application/org.openjdk.jmc.flightrecorder.flamegraph/plugin.xml @@ -1,7 +1,7 @@ @@ -9,9 +9,9 @@ -JDK Mission Control Eclipse Plug-in Online Help, Release 5.4 +JDK Mission Control Eclipse Plug-in Online Help, Release 10.0 - + @@ -30,15 +30,15 @@

JDK Mission Control

Eclipse Plug-in Online Help

-

Release 5.4

+

Release 9.1

E21555-05

-

August 2014

+

January 2025

Contains the online help topics for the Eclipse plug-in of JDK Mission Control.


-

JDK Mission Control Eclipse Plug-in Online Help, Release 5.4

+

JDK Mission Control Eclipse Plug-in Online Help, Release 10.0

E21555-05

-

Copyright © 2018, 2019, Oracle and/or its affiliates. All rights reserved.

+

Copyright © 2018, 2026, Oracle and/or its affiliates. All rights reserved.

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:

@@ -52,7 +52,7 @@

JDK Mission Control

-
+
Next
Next
diff --git a/application/org.openjdk.jmc.ide.ui/html/using003.htm b/application/org.openjdk.jmc.ide.ui/html/using003.htm index 2e31a0f6a..a4abc1601 100644 --- a/application/org.openjdk.jmc.ide.ui/html/using003.htm +++ b/application/org.openjdk.jmc.ide.ui/html/using003.htm @@ -1,7 +1,7 @@ @@ -33,7 +33,7 @@

Changing Your JVM

-

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:

  1. @@ -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/

  2. Depending upon your particular JVM implementation and the applications running on it, you can set any valid JVM command-line option.

    @@ -78,7 +78,7 @@

    Changing Your JVM

    -showsplash
    org.eclipse.platform
    -vm
    -C:\Program Files\Java\jdk1.7.0\bin\javaw.exe
    +C:\Program Files\Java\jdk21\bin\javaw.exe
    -vmargs
    -Dosgi.requiredJavaVersion=1.5
    -Xms256m
    @@ -92,7 +92,7 @@

    Changing Your JVM

    -
    +
    Previous
    Previous
      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.

    Bullet diff --git a/application/org.openjdk.jmc.updatesite.ide/src/main/resources/run-on-jdk-instructions/index.html b/application/org.openjdk.jmc.updatesite.ide/src/main/resources/run-on-jdk-instructions/index.html index ef3430d8b..64dc861fe 100644 --- a/application/org.openjdk.jmc.updatesite.ide/src/main/resources/run-on-jdk-instructions/index.html +++ b/application/org.openjdk.jmc.updatesite.ide/src/main/resources/run-on-jdk-instructions/index.html @@ -1,5 +1,5 @@ @@ -34,7 +34,7 @@

    To fully take advantage of running JDK Mission Control in your Eclipse IDE, you need to run Eclipse on a JDK installation.
    Attaching to locally running JVMs will only work if you're running with a JDK.

    Follow the instructions below to run on a HotSpot JDK.

    -

    The easiest way to change the JVM on which to start Eclipse is by modifying the eclipse.ini file. You can also set the -vm on the command line used to start Eclipse. In windows you would typically do that in the shortcut you use to launch Eclipse. Here is an example ini file:

    -showsplash
    org.eclipse.platform
    -vm
    D:/java/jdk-11.0.11/bin/

    +

    The easiest way to change the JVM on which to start Eclipse is by modifying the eclipse.ini file. You can also set the -vm on the command line used to start Eclipse. In windows you would typically do that in the shortcut you use to launch Eclipse. Here is an example ini file:

    -showsplash
    org.eclipse.platform
    -vm
    D:/java/jdk-21/bin/

    You can also configure JVM options by using -vmargs on commandline or eclipse.ini:

    -showsplash
    org.eclipse.platform
    -vm
    D:/java/jdk-11.0.11/bin/
    -vmargs
    <JVM options on separate lines>

    The following JVM options are needed for JDK Mission Control to work properly:

    -Djdk.attach.allowAttachSelf=true diff --git a/application/org.openjdk.jmc.updatesite.ide/src/main/resources/update-site-instructions/index.html b/application/org.openjdk.jmc.updatesite.ide/src/main/resources/update-site-instructions/index.html index ae8e8d74f..bf673b8b4 100644 --- a/application/org.openjdk.jmc.updatesite.ide/src/main/resources/update-site-instructions/index.html +++ b/application/org.openjdk.jmc.updatesite.ide/src/main/resources/update-site-instructions/index.html @@ -1,7 +1,7 @@ @@ -43,7 +43,7 @@

    Step-by-Step Instructions

    - Before starting, make sure that you have downloaded and installed Eclipse 4.31. + Before starting, make sure that you have downloaded and installed 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.encoder encoder - 1.2.3 + 1.4.0 at.yawk.lz4 lz4-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 @@