redhat-developer / redhat-developer/vscode-java
Gradle multi-project import materializes internal build/libs jars into live JDT classpath
@snjeza y travaille déjà.
Depuis le 21/4/2026.
- Langage dominant
- TypeScript
- Étoiles
- 2.3k
- Forks
- 546
- Merge moyen
- 20 h 1 min
- PR mergées (30 j)
- 11
Description
Summary
In a Gradle multi-project Java workspace, local subproject dependencies are resolved correctly as project references in the Buildship-saved model, but the live JDT/Eclipse project classpath is later materialized with internal build/libs/*.jar entries instead.
This causes local multi-module dependencies to behave like jar dependencies rather than live project/classfile dependencies, and can trigger stale or missing-library failures when those jars are rebuilt with different names.
Related discussion
- Original Cursor thread that led to this upstream investigation: Jar files auto-created and added to classpath on Cursor startup
I am filing here because the evidence points at the Java tooling / import / classpath materialization stack rather than a Cursor-specific layer.
Environment
- OS: Windows 11
- Java tooling: Language Support for Java by Red Hat
- Build tool: Gradle multi-project build
- Repo root:
C:\Users\<USER>\git\<REPO> - Affected example project:
admin-tools
Observed Java server startup includes:
-Djava.import.generatesMetadataFilesAtProjectRoot=false
Affected dependency shape
The affected project depends on local Gradle subprojects via normal project dependencies, for example:
project(":server-common")project(":db-common")project(":runtime-common")
Expected behavior
After import/reload, local Gradle subprojects should remain project references in the live Java project model.
The live classpath should not re-add internal jars from:
server-common/build/libs/*.jardb-common/build/libs/*.jarruntime-common/build/libs/*.jar
Actual behavior
After restart / re-import, the live classpath for admin-tools contains internal jars again, for example:
C:\Users\<USER>\git\<REPO>\runtime-common\build\libs\runtime-common-20260420175810.jarC:\Users\<USER>\git\<REPO>\db-common\build\libs\db-common-20260420175810.jarC:\Users\<USER>\git\<REPO>\server-common\build\libs\server-common-20260420175810.jar
These entries come back even if removed before restart.
Confirmed findings
1. Buildship-saved model is correct
File:
C:\Users\<USER>\AppData\Roaming\Cursor\User\workspaceStorage\<WORKSPACE_ID>\redhat.java\jdt_ws\.metadata\.plugins\org.eclipse.buildship.core\project-preferences\admin-tools
What was verified:
classpath=contains project refs such as/server-common,/db-common,/runtime-common- it contains normal external dependencies from
.gradle\caches - it does not contain internal repo jar paths under
<REPO>/*/build/libs
This strongly suggests the Buildship-side saved model is correct.
2. Live JDT/Eclipse classpath is wrong
File:
C:\Users\<USER>\AppData\Roaming\Cursor\User\workspaceStorage\<WORKSPACE_ID>\redhat.java\jdt_ws\.metadata\.plugins\org.eclipse.core.resources\.projects\admin-tools\.classpath
Observed contents include:
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="lib" path="C:/Users/<USER>/git/<REPO>/runtime-common/build/libs/runtime-common-20260420175810.jar"/>
<classpathentry kind="lib" path="C:/Users/<USER>/git/<REPO>/db-common/build/libs/db-common-20260420175810.jar"/>
<classpathentry kind="lib" path="C:/Users/<USER>/git/<REPO>/server-common/build/libs/server-common-20260420175810.jar"/>
So the live Eclipse/JDT classpath is being materialized incorrectly after the Buildship model is already correct.
3. Repo-root .classpath is not the active source
Before restart, these were deleted:
- repo-level
admin-tools/.classpath - workspace
org.eclipse.core.resources/.../admin-tools/.classpath - workspace
org.eclipse.buildship.core/project-preferences/admin-tools
After restart:
- the repo-level
admin-tools/.classpathdid not get recreated - the workspace live
.classpathdid get recreated - the Buildship
project-preferencesfile also got recreated
This suggests the active regeneration is happening from the Java workspace/import pipeline, not from repo-root Eclipse metadata.
4. Gradle eclipse customization produced the correct model-side result
I tested targeted eclipse.classpath.file.whenMerged customization in affected subprojects to:
- remove internal
build/libs/*.jarentries - add explicit project refs such as
/server-common,/db-common,/runtime-common
I then ran:
:admin-tools:eclipseClasspath:db-common:eclipseClasspath:runtime-common:eclipseClasspath
The generated .classpath outputs were correct immediately after generation, with project references present and internal local build/libs/*.jar entries absent.
This suggests the custom merge logic is not being ignored at the model-generation step.
5. Multiple importers were active in logs
Java language server logs showed multiple importers active, including:
GradleBuildServerProjectImporterGradleProjectImporterEclipseProjectImporter
That may be relevant if this is an importer precedence / post-processing issue.
6. Wrapper upgrade had no effect
I upgraded the project Gradle wrapper from 8.5 to 8.14.3 and re-tested.
The bad internal jar materialization still occurred, so this does not look like a simple mismatch between system Gradle and wrapper Gradle.
7. Disabling Gradle import was not a usable workaround
I also tested disabling java.import.gradle.enabled.
That severely broke import/build behavior rather than solving the classpath issue, so it does not appear to be a valid workaround.
Reproduction outline
- Open a Gradle multi-project Java workspace.
- Ensure one project depends on local subprojects via
implementation project(...). - Let Java/Gradle import complete.
- Inspect the Buildship-saved model under
org.eclipse.buildship.core/project-preferences/.... - Inspect the live Eclipse/JDT project classpath under
org.eclipse.core.resources/.projects/.../.classpath. - Observe that the saved model contains project refs, but the live classpath contains internal
build/libs/*.jarentries.
Impact
- breaks expected live multi-module development workflow
- makes the editor prefer built jar artifacts over local project/classfile references
- can reintroduce stale or timestamped jar references on restart
- can trigger missing-library failures when jar names change
Current hypothesis
The problem appears to happen after Buildship has already produced the correct model, during the step where org.eclipse.buildship.core.gradleclasspathcontainer is materialized into the live JDT/Eclipse project classpath.
If useful, I can provide the relevant anonymized project-preferences content, the resulting live .classpath, and the Java language server log excerpts showing the active importers.
Suggested investigation area
Please inspect how the Gradle/Buildship model is handed off to the live JDT project classpath, especially where org.eclipse.buildship.core.gradleclasspathcontainer is resolved and written into the live .classpath when local Gradle subprojects are already present as project references in the saved model.
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Évaluation
Cette issue n'a pas encore été évaluée.