Skip to content
Merged
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
142 changes: 142 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# JDK Mission Control (JMC) - Agent Instructions

## Project Overview
- Java Mission Control (JMC) is an OpenJDK project with core libraries and an Eclipse RCP UI.
- Main areas:
- `core/` - Headless Java 17 libraries (can run standalone, read recordings from JDK 7+)
- `org.openjdk.jmc.common` - Core APIs and utilities
- `org.openjdk.jmc.flightrecorder` - JFR parsing and analysis
- `org.openjdk.jmc.flightrecorder.rules` - Rule framework
- `org.openjdk.jmc.flightrecorder.rules.jdk` - JDK-specific analysis rules
- `org.openjdk.jmc.testlib` - Test utilities
- `application/` - Eclipse RCP UI components (Java 21)
- `agent/` - JFR Agent for bytecode instrumentation

## Build & Test
- `./build.sh --installCore` - Install core libraries
- `./build.sh --packageJmc` - Package full JMC application
- `./build.sh --test` - Run standard tests
- `./build.sh --testUi` - Run UI tests
- `mvn verify -Dtest.includes=**/*TestName*` - Run specific tests
- `mvn verify -Dspotbugs.skip=true` - Skip SpotBugs during verification

### Build Scripts
- `scripts/runcoretests.sh` - Run core library tests
- `scripts/runapptests.sh` - Run application tests
- `scripts/runagenttests.sh` - Run agent tests
- `scripts/startp2.sh` - Start local P2 repository for application build

### Eclipse Platform Profiles
Build against specific Eclipse platform versions using Maven profiles:
```bash
mvn verify -P 2024-12
```

## Java Version & Toolchains
- **Java Version**: JDK 21 for application build, JDK 17 for core components
- Requires both JDK 17 and JDK 21 configured in `~/.m2/toolchains.xml`.

Example `~/.m2/toolchains.xml`:
```xml
<toolchains>
<toolchain>
<type>jdk</type>
<provides>
<id>JavaSE-17</id>
<version>17</version>
</provides>
<configuration>
<jdkHome>/path/to/jdk17</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<id>JavaSE-21</id>
<version>21</version>
</provides>
<configuration>
<jdkHome>/path/to/jdk21</jdkHome>
</configuration>
</toolchain>
</toolchains>
```

## Code Style & Formatting
- Java formatting follows the Eclipse profile in `configuration/ide/eclipse/formatting/formatting.xml`.
- Java cleanup rules are in `configuration/ide/eclipse/formatting/clean-up-with-formatting.xml`.
- JavaScript formatting follows `configuration/ide/eclipse/formatting/formattingjs.xml`.
- Key formatter settings (from the Eclipse profiles):
- Tabs for indentation (`tabulation.char=tab`, size 4).
- Line length 120 (`lineSplit=120`).
- Javadoc/comment line length 100 (`comment.line_length=100`).
- Avoid star imports; remove unused imports.
- **Naming**: Follow Eclipse/Java standard conventions, be consistent.

## Logging / Error Handling
- Use `Level.FINE` for expected exceptions (e.g., `CancellationException`).
- Use `Level.SEVERE` for unexpected failures.
- Filter cancellations from error logs during model rebuilding.
- Check SpotBugs exceptions for guidance.

## Commit Messages
- Format: `JIRA_NUMBER: Commit message` (example: `6789: Fix bug`).
- Issue tracker: https://bugs.openjdk.org/projects/JMC/issues

## Copyright Headers
- All modified files must have the current year in the copyright header.
- CI validates this via `scripts/checkcopyrightyear.sh`.
- Affected file types: `*.java`, `*.htm`, `pom.xml`, `*.properties`.

## Static Analysis
- **Checkstyle**: Enforces no star imports, no redundant/unused imports (`configuration/checkstyle/checkstyle.xml`).
- **SpotBugs**: Static bug detection with exclusions in `configuration/spotbugs/spotbugs-exclude.xml`.
- **Spotless**: Code formatting enforced during Maven validate phase.

## Internationalization (i18n)
- Core modules: Place `messages.properties`, `messages_ja.properties`, `messages_zh.properties` in `internal` packages.
- Application modules: Use separate l10n plugin modules (e.g., `org.openjdk.jmc.*.ja`, `org.openjdk.jmc.*.zh_CN`).
- Access strings via `Messages.getString(Messages.MESSAGE_KEY)`.

## Writing Flight Recorder Rules
Rules analyze JFR recordings and provide recommendations to users.

### Creating a New Rule
1. Extend `AbstractRule`:
```java
public class MyRule extends AbstractRule {
public MyRule() {
super("MyRuleId", Messages.getString(Messages.MY_RULE_NAME),
JfrRuleTopics.TOPIC_NAME, CONFIGURATION_ATTRIBUTES,
RESULT_ATTRIBUTES, Collections.emptyMap());
}

@Override
protected IResult getResult(IItemCollection items, IPreferenceValueProvider vp,
IResultValueProvider rp) {
// Analyze items using ItemFilters, Aggregators, etc.
return ResultBuilder.createFor(this, vp)
.setSeverity(Severity.get(score))
.setSummary("Summary message")
.setExplanation("Detailed explanation")
.build();
}
}
```

2. Register the rule in `META-INF/services/org.openjdk.jmc.flightrecorder.rules.IRule`:
```
org.openjdk.jmc.flightrecorder.rules.jdk.mypackage.MyRule
```

### Core Item Processing APIs
- `IItemCollection` - Collection of JFR events to query
- `IItemFilter` - Filter events (use `ItemFilters` factory)
- `IAggregator` - Aggregate values (use `Aggregators` factory)
- `IAttribute` - Access event attributes (see `JdkAttributes`)
- `RulesToolkit` - Utility methods for rule implementations

## Testing
- Unit tests in `src/test/java` using JUnit 4.
- Test resources in `src/test/resources`.
- JDP multicast tests are automatically skipped on macOS.
3 changes: 1 addition & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ message should be "6789: Commit message".

The mailing list for JDK Mission Control is `jmc-dev@openjdk.java.net`. See
<https://mail.openjdk.java.net/mailman/listinfo/jmc-dev> for instructions
on how to subscribe of if you want to read the archives.
on how to subscribe or if you want to read the archives.

## Issues

Expand Down Expand Up @@ -45,4 +45,3 @@ If not, ask for an invite in the jmc-dev mailing list.

If you have a question or need help, please send an email to our mailing list
`jmc-dev@openjdk.java.net` or stop by the JMC slack channel.

4 changes: 2 additions & 2 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Contributors
# Contributors

A lot of people have been involved with Mission Control over the years.
This document is a thank you to everyone who has ever contributed to
Expand Down Expand Up @@ -31,4 +31,4 @@ List of contributors, approximately in order of time spent on project:
* Suchita Chaturvedi
* Guru Hb
* Sharath Ballal
* Peter Boström
* Peter Boström
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Mission Control is an open source production time profiling and diagnostics tool for Java.

Builds of Mission Control can currently be found in the Oracle JDK on supported platforms and in the Eclipse marketplace.
Builds of Mission Control can currently be found in the Oracle JDK on supported platforms and in the Eclipse Marketplace.

For more information on Mission Control, see https://www.oracle.com/missioncontrol.

Expand Down Expand Up @@ -217,7 +217,7 @@ Prerequisites for building Mission Control:

2. Install a JDK 21 distribution and make sure that it too is declared in the local maven toolchain.

3. Install Maven (version 3.5.x. or above)
3. Install Maven (version 3.5.x or above)

On Linux or macOS you can use the `build.sh` script to build JMC:
```
Expand Down Expand Up @@ -268,7 +268,7 @@ If maven reports a toolchain error, e.g. :
[ERROR] Please make sure you define the required toolchains in your ~/.m2/toolchains.xml file.
```

Create or amend the local maven toolchain file by pointing to the right/any JDK 17.
Create or amend the local maven toolchain file by pointing to any JDK 17 installation.

<details><summary><code>~/.m2/toolchains.xml</code></summary>

Expand Down Expand Up @@ -346,7 +346,7 @@ mvn verify -P uitests -Dspotbugs.skip=true
```

## Filtering Test Runs
Aside from the from the simple -test Maven flag test classes that should be run/not run can be specified by means of the system properties "test.includes" and/or "test.excludes". Multiple patterns can be specified by comma separation.
Aside from the simple -test Maven flag, test classes that should be run/not run can be specified by means of the system properties "test.includes" and/or "test.excludes". Multiple patterns can be specified by comma separation.

For example:

Expand Down Expand Up @@ -422,7 +422,7 @@ There is another update site for the Eclipse plug-ins, providing plug-ins for ru
application/org.openjdk.jmc.updatesite.ide/target/
```

To install it into Eclipe, simply open Eclipse and select Help | Install New Software... In the dialog, click Add... and then click the Archive... button. Select the built update site, e.g.
To install it into Eclipse, simply open Eclipse and select Help | Install New Software... In the dialog, click Add... and then click the Archive... button. Select the built update site, e.g.

```bash
application/org.openjdk.jmc.updatesite.ide/target/org.openjdk.jmc.updatesite.ide-10.0.0-SNAPSHOT.zip
Expand Down
9 changes: 7 additions & 2 deletions application/coverage/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2019, 2025, Red Hat Inc. All rights reserved.
Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2019, 2026, Red Hat Inc. All rights reserved.

DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.

Expand Down Expand Up @@ -267,6 +267,11 @@
<artifactId>org.openjdk.jmc.ui.celleditors</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmc</groupId>
<artifactId>org.openjdk.jmc.ui.websocket</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmc</groupId>
<artifactId>org.openjdk.jmc.ui.common</artifactId>
Expand Down
9 changes: 8 additions & 1 deletion application/org.openjdk.jmc.feature.core/feature.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.

Expand Down Expand Up @@ -166,6 +166,13 @@
version="0.0.0"
unpack="false"/>

<plugin
id="org.openjdk.jmc.ui.websocket"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>

<plugin
id="org.openjdk.jmc.rjmx.common"
download-size="0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Require-Bundle: org.openjdk.jmc.rjmx,
org.openjdk.jmc.flightrecorder.configuration,
org.openjdk.jmc.commands,
org.openjdk.jmc.browser,
org.openjdk.jmc.ui.websocket,
org.hdrhistogram.HdrHistogram,
org.eclipse.jetty.io,
org.eclipse.jetty.websocket.server,
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*
Expand Down Expand Up @@ -143,23 +143,6 @@ public static IQuantity parseItemListSize(String size) {
}
}

public static int parseWebsocketPort(String port) {
try {
return Integer.parseInt(port);
} catch (NumberFormatException e) {
return PreferenceKeys.DEFAULT_WEBSOCKET_PORT;
}
}

public int getWebsocketPort() {
return parseWebsocketPort(getPreferenceStore().getString(PreferenceKeys.PROPERTY_WEBSOCKET_SERVER_PORT));
}

public boolean isWebsocketServerEnabled() {
int port = getWebsocketPort();
return port > 0 && port < 65535;
}

public static String validateDumpTimespan(String text) {
try {
IQuantity timespan = UnitLookup.TIMESPAN.parseInteractive(text);
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*
Expand Down Expand Up @@ -83,13 +83,13 @@
import org.openjdk.jmc.flightrecorder.ui.preferences.PreferenceKeys;
import org.openjdk.jmc.flightrecorder.ui.selection.IFlavoredSelection;
import org.openjdk.jmc.flightrecorder.ui.selection.SelectionStore;
import org.openjdk.jmc.flightrecorder.ui.websocket.WebsocketServer;
import org.openjdk.jmc.ui.MCPathEditorInput;
import org.openjdk.jmc.ui.idesupport.IDESupportUIToolkit;
import org.openjdk.jmc.ui.misc.CompositeToolkit;
import org.openjdk.jmc.ui.misc.DialogToolkit;
import org.openjdk.jmc.ui.misc.DisplayToolkit;
import org.openjdk.jmc.ui.misc.SelectionProvider;
import org.openjdk.jmc.ui.websocket.WebsocketPlugin;

public class JfrEditor extends EditorPart implements INavigationLocationProvider, IPageContainer {

Expand All @@ -113,8 +113,6 @@ public class JfrEditor extends EditorPart implements INavigationLocationProvider
private Reference<ResultPage> resultPageRef = new WeakReference<>(null);
private RuleManager ruleEngine;
private IPropertyChangeListener analysisEnabledListener;
private IPropertyChangeListener websocketServerEnabledListener;
private WebsocketServer websocketServer;

public JfrEditor() {
super();
Expand All @@ -126,29 +124,7 @@ public JfrEditor() {
}
}
};
if (FlightRecorderUI.getDefault().isWebsocketServerEnabled()) {
int websocketServerPort = FlightRecorderUI.getDefault().getWebsocketPort();
websocketServer = new WebsocketServer(websocketServerPort);
}
websocketServerEnabledListener = e -> {
if (e.getProperty().equals(PreferenceKeys.PROPERTY_WEBSOCKET_SERVER_PORT)) {
int newWebsocketServerPort = FlightRecorderUI.parseWebsocketPort((String) e.getNewValue());
if (newWebsocketServerPort > 0) {
if (websocketServer != null) {
websocketServer.shutdown();
websocketServer = null;
}
websocketServer = new WebsocketServer(newWebsocketServerPort);
} else {
if (websocketServer != null) {
websocketServer.shutdown();
websocketServer = null;
}
}
}
};
FlightRecorderUI.getDefault().getPreferenceStore().addPropertyChangeListener(analysisEnabledListener);
FlightRecorderUI.getDefault().getPreferenceStore().addPropertyChangeListener(websocketServerEnabledListener);
}

@Override
Expand Down Expand Up @@ -214,8 +190,8 @@ public void showSelection(IItemCollection items) {
if (!items.hasItems() && currentPage != null) {
selectionItems = getModel().getItems().apply(getDisplayablePage(currentPage).getDefaultSelectionFilter());
}
if (websocketServer != null) {
websocketServer.notifyAll(selectionItems);
if (WebsocketPlugin.getDefault().getServerEnabled() == true) {
WebsocketPlugin.getDefault().notifyAll(selectionItems);
}
getSite().getSelectionProvider().setSelection(new StructuredSelection(selectionItems));
}
Expand Down Expand Up @@ -429,7 +405,6 @@ public RuleManager getRuleManager() {
public void dispose() {
ruleEngine.dispose();
FlightRecorderUI.getDefault().getPreferenceStore().removePropertyChangeListener(analysisEnabledListener);
FlightRecorderUI.getDefault().getPreferenceStore().removePropertyChangeListener(websocketServerEnabledListener);
super.dispose();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*
Expand Down Expand Up @@ -475,9 +475,6 @@ public class Messages extends NLS {
public static String PREFERENCES_RULES_CONFIGURE_SELECTED;
public static String PREFERENCES_SHOW_MONITORING_WARNING_TEXT;
public static String PREFERENCES_STACKTRACE_SHOW_HIDDEN_FRAMES;
public static String PREFERENCES_WEBSOCKET_SERVER_PORT_INVALID;
public static String PREFERENCES_WEBSOCKET_SERVER_PORT_TEXT;
public static String PREFERENCES_WEBSOCKET_SERVER_PORT_TOOLTIP;
public static String ProcessesPage_AGGR_CONCURRENT_PROCESSES;
public static String ProcessesPage_AGGR_CONCURRENT_PROCESSES_DESC;
public static String ProcessesPage_AGGR_FIRST_SAMPLE;
Expand Down
Loading