[Bug] jdtls-lsp spawns per-subagent instances causing >50 GB RAM exhaustion in large Java workspaces

Resolved 💬 6 comments Opened Jun 1, 2026 by maynestream-dev Closed Jul 5, 2026

Bug Description
TITLE: jdtls-lsp is unusable in real-world Java projects: per-subagent spawning under
claude agents causes >50 GB RAM exhaustion and forces hard machine resets

SEVERITY: Critical and feature-breaking. Has forced hard machine resets at least 3
times, with loss of unsaved work, corrupted in-flight git state, and interrupted
long-running builds each time. Beyond the data-loss risk, the practical effect is
that I cannot enable Java LSP on the only project where I genuinely need it — a
production enterprise monorepo. The feature works on toy projects and fails exactly
in the environment it is supposed to serve. My only available workaround is to
disable jdtls-lsp on this project, which means the LSP delivers zero value where it
matters most.

ENVIRONMENT

  • macOS (Apple Silicon)
  • Claude Code 2.1.150
  • Plugin: jdtls-lsp@claude-plugins-official (version 1.0.0)
  • jdtls 1.58.0 via Homebrew, Java 21 (Amazon Corretto)
  • Workspace: Gradle composite build with 90+ services + multiple library modules
  • Workflow: routine use of claude agents with 3–6 concurrent subagents on Java code

REPRODUCTION

  1. Open a large Java workspace (composite Gradle build with ~90+ subprojects)
  2. Run claude agents and dispatch several subagents that touch Java files
  3. Observe ps -eo pid,ppid,rss,command | grep equinox.launcher

one JDTLS instance per Claude Code process subtree, each ~2–3 GB RSS

  1. With 3+ concurrent Java-touching agents, total Java RSS climbs past 7 GB; with

sustained multi-agent activity over a session, observed total has exceeded 50 GB,
forcing hard reset

ROOT CAUSE (from local investigation)

  • ~/.claude/plugins/cache/claude-plugins-official/jdtls-lsp/1.0.0/ contains only

LICENSE, README.md, and an .in_use/ directory. No manifest, no MCP server
definition, no spawn script. JDTLS spawning logic lives in Claude Code core,
not the plugin — there are no plugin-side configuration knobs by design.

  • Each Claude Code process subtree that touches Java spawns its OWN JDTLS instance.

No sharing or multiplexing across subagents of the same claude agents session,
even when every subagent is operating on the same workspace.

  • The .in_use/ directory contains a PID-named file per CC process that ever claimed

the plugin. In my install it contains 90 entries; only ~10 are live PIDs. The
rest are orphans from CC processes that exited without cleanup. This is a
ref-count leak in the registration mechanism.

WHY OBVIOUS-LOOKING FIXES ARE NOT FIXES

  1. "Just cap the JDTLS heap (e.g. expose JDTLS_JVM_ARGS)."

Eclipse JDT.LS does not gracefully degrade under tight heap on a 90-module
composite build — it OOMs mid-index, drops requests, and returns incomplete
results (missing symbols, wrong references, partial diagnostics). A
memory-capped LSP is a wrong-answer LSP. This makes the feature useless in a
different way and should not be considered a resolution.

  1. "Just disable the plugin per-project."

This IS my current workaround. It is also exactly what makes this a
feature-breaking bug: I have to turn the feature off in the only project
where I would benefit from it. If the recommendation is "disable on big
projects", then jdtls-lsp should not be marketed as a Java LSP for Claude
Code — it is a Java LSP for hobby projects only.

  1. "Add a circuit-breaker that refuses to spawn the Nth instance."

This converts a crash into a silent feature failure. The Nth subagent would
silently lose code intelligence with no signal that it has done so, producing
worse results than disabling the plugin outright.

THE ONLY ACCEPTABLE FIX
One JDTLS instance per workspace, shared across all subagents within the same
claude agents session (or across all CC processes rooted at the same project
directory). Subagents must multiplex LSP requests through a single long-lived
language server — this is how every other multi-process LSP host works
(VS Code Remote, IntelliJ, Helix, Zed). This is an architectural change in
Claude Code core, not a plugin tweak. The fact that the plugin is a metadata-
only shim means the work has to happen in core regardless.

Until that architectural fix lands, jdtls-lsp should be marked as
experimental / unsuitable for projects above some size threshold in its README,
so users with large Java workspaces are not blindsided by the crash mode.

SECONDARY BUG (separate, easily fixed)
Clean up stale .in_use/<pid> entries on plugin claim/release, or use a
filesystem lock with a TTL. The current accumulation is a real leak even if it
isn't the cause of the memory exhaustion.

WHY THIS MATTERS

  • Hard machine resets risk data loss, corrupt git state, lost editor buffers,

interrupted long-running builds, damaged Docker state

  • Multi-agent / FleetView is a marquee CC feature; combining it with Java work

in a real enterprise monorepo is currently a crash hazard

  • The feature is silently broken for exactly the enterprise users CC is targeting

ATTACHMENTS / DIAGNOSTICS
Happy to share full process snapshots, plugin directory contents, and ~/.claude
config files if helpful.

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗