Skip to content

launching: Add file based configuration of installed JREs and EE defaults - #1047

Open
peterkir wants to merge 1 commit into
eclipse-jdt:masterfrom
peterkir:jre-configuration-file
Open

peterkir wants to merge 1 commit into
eclipse-jdt:masterfrom
peterkir:jre-configuration-file

Conversation

@peterkir

Copy link
Copy Markdown

Adds an optional JSON (JSONC) configuration file to provision Installed JREs and the default VM per Execution Environment at startup, for headless / managed / CI setups where editing the org.eclipse.jdt.launching.PREF_VM_XML preference string or writing a plugin for the vmInstalls extension point is impractical.

Activation (first match wins, all optional)

  1. command line argument -jreConfig <file> (also -jreConfig=<file>)
  2. system property -Dorg.eclipse.jdt.launching.jreConfig=<file>
  3. environment variable JDT_JRE_CONFIG=<file>

Without any of these the code path is not entered and behaviour is unchanged. No API is added or changed; everything new is in org.eclipse.jdt.internal.launching.

File format

{
  "java.configuration.runtimes": [
    {
      "label":   "[JDK 21] Temurin 21.0.6+7-LTS",   // required, VM name
      "path":    "C:\\jdks\\temurin-21",            // required, supports ${variable} substitution
      "version": "JavaSE-21",                       // optional, EE id used as fallback EE default
      "vendor":  "Temurin",                         // optional, stored as VM attribute "vendor"
      "sources": "C:\\jdks\\temurin-21\\lib\\src.zip", // optional, source attachment
      "javadoc": "https://docs.oracle.com/en/java/javase/21/docs/api/", // optional
      "vmArgs":  "-Xmx2g",                          // optional
      "default": true                               // optional, workspace default JRE
    }
  ],
  "java.configuration.ee": [
    { "ee": "JavaSE-21", "path": "C:\\jdks\\temurin-21" }
  ]
}

The key names intentionally match the java.configuration.runtimes setting of the VS Code Java extension so existing files can be reused.

Semantics

  • Applied in JavaRuntime.initializeVMs() as step 2b (after persisted VMs, before Eclipse runtime detection): a runtime whose install location already exists in the container is updated in place (id kept), otherwise a VMStandin of the standard VM type is added. VMs are never removed, nothing is duplicated. Invalid locations are logged and skipped, never abort startup.
  • On a fresh workspace the first runtime (or the one flagged default) becomes the default JRE and compiler compliance is aligned, mirroring the existing runtime detection path.
  • EE defaults are applied in EnvironmentsManager.initializeDefaultVMs() after the persisted defaults: explicit java.configuration.ee entries override, a runtime version only fills environments that have no default yet. Incompatible VMs are logged and skipped.
  • JSON is read by a small dependency free parser (SimpleJsonParser, tolerates comments and trailing commas), avoiding a new bundle dependency.

Testing

  • JreConfigurationFileTests (added to AutomatedSuite): parser, config validation, container merge/update/default/skip-invalid. Passes via mvn -Pbuild-individual-bundles verify -pl org.eclipse.jdt.debug.tests -am -DtestClass=org.eclipse.jdt.debug.tests.core.JreConfigurationFileTests.
  • Headless Equinox run with the patched bundle and six real JDKs: fresh workspace, second start with modified file (rename in place, default switch, sources override, EE remap), no file (baseline unchanged), env variable activation.

@peterkir
peterkir force-pushed the jre-configuration-file branch from e5192c5 to 779ab97 Compare October 21, 2026 09:23
@SougandhS

Copy link
Copy Markdown
Member

Hi @peterkir
It's mandatory that ECA is signed before PR can be accepted https://api.eclipse.org/git/eca/status/gh/eclipse-platform/eclipse.platform/3026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

VM naming and rename handling can select the wrong JDK or break existing project and launch references.

5 open issues
What changed in this PR

Adds optional JSON/JSONC provisioning of installed JREs and execution-environment defaults for managed, headless, and CI workspaces.

Changes:

  • Loads configuration through command-line, system-property, or environment-variable activation.
  • Integrates runtime merging and environment defaults into initialization.
  • Adds parser, validation, and VM configuration tests.
File Description
org.eclipse.jdt.launching/​launching/​org/​eclipse/​jdt/​launching/​JavaRuntime.java Integrates configuration into VM initialization.
org.eclipse.jdt.launching/​launching/​org/​eclipse/​jdt/​internal/​launching/​SimpleJsonParser.java Adds dependency-free JSONC parsing.
org.eclipse.jdt.launching/​launching/​org/​eclipse/​jdt/​internal/​launching/​JreConfigurationFile.java Loads configuration and merges runtime definitions.
org.eclipse.jdt.launching/​launching/​org/​eclipse/​jdt/​internal/​launching/​environments/​EnvironmentsManager.java Applies configured environment defaults.
org.eclipse.jdt.debug.tests/​tests/​org/​eclipse/​jdt/​debug/​tests/​core/​JreConfigurationFileTests.java Tests parsing, validation, and runtime merging.
org.eclipse.jdt.debug.tests/​tests/​org/​eclipse/​jdt/​debug/​tests/​AutomatedSuite.java Registers the new tests.

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Invalid configured paths can abort VM initialization, and case-only Javadoc URL changes are lost for explicit libraries.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Preserve case-only explicit library URL changes

org.eclipse.jdt.launching/​launching/​org/​eclipse/​jdt/​internal/​launching/​JreConfigurationFile.java:542

With unchanged sources, a case-only change to an explicit library's Javadoc URL is discarded here. LibraryLocation.equals() uses LaunchingPlugin.sameURL(), which lowercases non-file URLs, so changing /API/ to /api/ leaves librariesChanged false. These paths can serve different content, and JREContainer uses the old explicit-library URL rather than the updated VM-level URL. Preserve case-sensitive URL changes in both this comparison and AbstractVMInstall.setLibraryLocations(), whose equality check would also discard the update. Add a regression test for a case-only URL change with unchanged sources.

5 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Unresolved configuration correctness issues and missing execution-environment application tests prevent approval.

No open issues 🎉

5 previously missed issues

In code that hasn't changed since last review

Medium severity Preserve VM Javadoc when adding sources

org.eclipse.jdt.launching/​launching/​org/​eclipse/​jdt/​internal/​launching/​JreConfigurationFile.java:539

For an existing VM with implicit libraries and a custom VM-level Javadoc URL, specifying only sources loads the type defaults here rather than the VM's effective libraries. Once these become explicit library locations, JREContainer.computeClasspathEntries() no longer applies the VM-level URL, so adding sources silently replaces or removes the existing documentation attachment. Use JavaRuntime.getLibraryLocations(standin) to preserve the effective Javadoc URL, and add a sources-only regression test.

Medium severity Compare Javadoc URL paths case-sensitively

org.eclipse.jdt.launching/​launching/​org/​eclipse/​jdt/​internal/​launching/​JreConfigurationFile.java:549

For explicit libraries, a Javadoc URL change from /API/ to /api/ leaves projects using the old URL because LibraryLocation.equals() compares HTTP URLs case-insensitively. Preserve case-sensitive URL paths in both this comparison and the equality check used by AbstractVMInstall.setLibraryLocations(); changing this comparison alone will not make the setter accept the update. Add a regression test for a case-only Javadoc path change.

Medium severity Reject unescaped control characters in strings

org.eclipse.jdt.launching/​launching/​org/​eclipse/​jdt/​internal/​launching/​SimpleJsonParser.java:222

The parser accepts literal LF, TAB, and NUL characters inside strings, although JSON and JSONC require them to be escaped. Malformed configuration values therefore reach provisioning instead of producing a syntax error. Reject characters below U+0020 in this branch and add rejection tests, while continuing to allow their escaped forms.

Medium severity Cover environment mapping precedence and compatibility

org.eclipse.jdt.launching/​launching/​org/​eclipse/​jdt/​internal/​launching/​environments/​EnvironmentsManager.java:369

The new tests parse EE mappings but never exercise their application through EnvironmentsManager. Please add automated coverage for explicit mappings overriding persisted defaults, runtime version preserving an existing default, and incompatible VMs being rejected. ExecutionEnvironmentTests already exercises this manager; these new precedence and compatibility branches currently have no regression protection.

Medium severity Validate runtime labels before setting EE defaults

org.eclipse.jdt.launching/​launching/​org/​eclipse/​jdt/​internal/​launching/​environments/​EnvironmentsManager.java:395

A runtime rejected for an invalid label can still set an execution environment's default here when its path matches an already-installed compatible VM. For example, Temurin/JDK21 is logged as ignored by addVMs(), but its version still fills an unset default. Apply the same label validation in this fallback pass so that the rejected entry cannot change EE settings.

1 resolved since last review

Review effort: Balanced

@SougandhS

Copy link
Copy Markdown
Member

Hi @peterkir, please squash all 4 commits to one and rebase on master, also check the failing test case

@peterkir
peterkir force-pushed the jre-configuration-file branch from 44616bc to 5fc0342 Compare October 26, 2026 06:05
@peterkir

Copy link
Copy Markdown
Author

Done in 5fc0342: squashed the four commits into one and rebased onto master (f6084c4). Investigated the failing Jenkins test via the GitHub check output: testInvalidLabelIsSkipped assumed backslash is invalid on every OS, but Unix permits it in filenames. The assertion now follows the platform filename rule, matching the existing Installed JREs UI validation. Targeted Tycho build passes after the rebase: 12 tests, 0 failures/errors. CI will validate the Linux run. Unrelated local IDE import settings were not included.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Explicitly empty VM arguments leave previously configured arguments active instead of clearing them.

1 open issue

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Javadoc configuration handling can lose existing overrides and ignore case-only URL path updates.

3 open issues

Review effort: Balanced

IPath sourcePath = runtime.sources() != null ? IPath.fromOSString(runtime.sources().getAbsolutePath()) : library.getSystemLibrarySourcePath();
URL javadoc = runtime.javadoc() != null ? runtime.javadoc() : library.getJavadocLocation();
updated[i] = new LibraryLocation(library.getSystemLibraryPath(), sourcePath, library.getPackageRootPath(), javadoc, library.getIndexLocation(), library.getExternalAnnotationsPath());
librariesChanged |= !updated[i].equals(library);

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Startup provisioning has an unresolved error-handling issue, and execution-environment selection lacks automated regression coverage needed for confidence without human validation.

3 open issues
2 resolved since last review

Review effort: Balanced

try {
javadocURL = URI.create(substitute(javadoc)).toURL();
} catch (IllegalArgumentException | MalformedURLException e) {
throw new IllegalArgumentException("Invalid javadoc URL for runtime '" + label + "': " + javadoc, e); //$NON-NLS-1$ //$NON-NLS-2$
Comment on lines +367 to +369
JreConfigurationFile configuration = JreConfigurationFile.getInstance();
if (configuration != null) {
applyConfiguredDefaultVMs(configuration);
Provision installed JREs and execution environment defaults from an optional JSON/JSONC file selected by command line, system property or environment variable. Merge existing installations without removing user VMs, preserve rename notifications and contributed VM ownership, and validate configured names and paths. Leave behavior unchanged when no configuration file is selected.

Preserve effective source and Javadoc attachments, including case-sensitive URL changes, and allow explicitly empty VM arguments to clear persisted values. Skip runtimes with malformed Javadoc URLs without discarding valid configuration and reject unescaped control characters.

Cover parsing, merging, contributions, renames, invalid paths and labels, attachment updates, and execution environment override, fallback and compatibility behavior with regression tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@peterkir
peterkir force-pushed the jre-configuration-file branch from 6e24278 to 0b8fd89 Compare October 27, 2026 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants