fix(run): Shorten java command lines too long for the OS (#28) (#45)

Root cause: every java launch inlined the whole classpath into one -cp argument with no "Shorten command line", so long classpaths exceeded CreateProcessW's 32767-char limit (os error 206) before the JVM started.
Fix (IDEA's auto "Shorten command line"): ide-run rewrites a too-long java command line at spawn time — @argfile on JDK 9+ with ASCII paths, otherwise a MANIFEST pathing jar (percent-encoded file: URLs, 72-byte lines); temp files are removed when the process exits. Debug passes the same choice to java-debug's shortenCommandLine.
Siblings covered: Application/Spring Boot, test classpath, Kotlin main, explicit java -cp configs, profiler, PTY launches, Debug.
Verified: unit tests, pathing jar loaded by real JDK 8/11/25, ProcessManager integration test with 3000 entries on JDK 8/17/25. Not verified on Windows.

Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-10-27 10:13:31 +08:00
1 джерело de84a643aa
коміт 1127263ea8
12 files changed
+647 -2

No files matched your search

+12
Переглянути файл
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
import type { RunConfig } from "@/platform/ipc";
const invoked: Array<[string, unknown[]]> = [];
let shortenCommandLine: string | null = null;
vi.mock("@/platform/ipc", async (orig) => {
const real = await orig<typeof import("@/platform/ipc")>();
const ok = (data: unknown) => Promise.resolve({ status: "ok", data });
@@ -18,6 +19,7 @@ vi.mock("@/platform/ipc", async (orig) => {
modulePaths: [],
javaHome: "/jdk21",
javaExec: "/jdk21/bin/java",
shortenCommandLine,
errors: [],
errorCount: 0,
hints: [],
@@ -49,6 +51,7 @@ const app: RunConfig = {
describe("Java debugging (java-debug through jdtls)", () => {
beforeEach(() => {
invoked.length = 0;
shortenCommandLine = null;
});
it("launches Application configs with the resolved classpath on jdtls' debug server", async () => {
@@ -68,9 +71,18 @@ describe("Java debugging (java-debug through jdtls)", () => {
vmArgs: "-Xmx1g",
args: '--port "8081 x"',
console: "internalConsole",
shortenCommandLine: "none",
});
});
it("lets java-debug shorten a classpath too long for the OS, as Run does", async () => {
for (const how of ["jarmanifest", "argfile"]) {
shortenCommandLine = how;
const l = await javaLaunchConfig(app, "/p");
expect(JSON.parse(l.extraJson!).shortenCommandLine).toBe(how);
}
});
it("attaches to a JDWP agent", async () => {
const l = await javaAttachConfig({ name: "mvn test", module: "", hostName: "127.0.0.1", port: 5005 }, "/p");
expect(l).toMatchObject({ request: "attach", cwd: "/p" });