Skip to content

Commit 99645e1

Browse files
authored
Fix process watcher path detection (#1427)
* Enhance JDK detection logic and add validation for configured Java home * Updated function naming
1 parent 5873b04 commit 99645e1

File tree

1 file changed

+61
-8
lines changed

1 file changed

+61
-8
lines changed

src/daemon/processWatcher.ts

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,55 @@ export class ProcessWatcher {
3434
if (!javaExt) {
3535
return false;
3636
}
37-
// get embedded JRE Home
37+
38+
// First check java.jdt.ls.java.home setting
3839
let jreHome: string | undefined;
39-
try {
40-
const jreFolder = path.join(javaExt.extensionPath, "jre");
41-
const jreDistros = await fs.promises.readdir(jreFolder);
42-
if (jreDistros.length > 0) {
43-
jreHome = path.join(jreFolder, jreDistros[0]);
40+
let configJavaHome = vscode.workspace.getConfiguration().get<string>('java.jdt.ls.java.home');
41+
42+
// If user has explicitly configured a Java home, use that
43+
if (configJavaHome) {
44+
if (await this.isValidJpsPath(configJavaHome)) {
45+
jreHome = configJavaHome;
46+
} else {
47+
// Log warning but continue with fallback
48+
console.warn(`Configured Java home ${configJavaHome} is not valid or not accessible. Checking other options.`);
49+
}
50+
}
51+
52+
// If not found, check for default runtime in java.configuration.runtimes
53+
if (!jreHome) {
54+
const runtimes = vscode.workspace.getConfiguration().get<any[]>('java.configuration.runtimes');
55+
if (Array.isArray(runtimes) && runtimes.length > 0) {
56+
// First look for one marked as default
57+
const defaultRuntime = runtimes.find(r => r.default === true);
58+
if (defaultRuntime && defaultRuntime.path) {
59+
if (await this.isValidJpsPath(defaultRuntime.path)) {
60+
jreHome = defaultRuntime.path;
61+
}
62+
}
63+
64+
// If no default is set or default is invalid, try the first one
65+
if (!jreHome && runtimes[0].path) {
66+
if (await this.isValidJpsPath(runtimes[0].path)) {
67+
jreHome = runtimes[0].path;
68+
}
69+
}
70+
}
71+
}
72+
73+
// If no valid JDK is found in settings, fall back to embedded JRE
74+
if (!jreHome) {
75+
try {
76+
const jreFolder = path.join(javaExt.extensionPath, "jre");
77+
const jreDistros = await fs.promises.readdir(jreFolder);
78+
if (jreDistros.length > 0) {
79+
jreHome = path.join(jreFolder, jreDistros[0]);
80+
}
81+
} catch (error) {
82+
// do nothing when jre is not embedded, to avoid spamming logs
4483
}
45-
} catch (error) {
46-
// do nothing when jre is not embedded, to avoid spamming logs
4784
}
85+
4886
if (!jreHome) {
4987
return false;
5088
}
@@ -96,6 +134,21 @@ export class ProcessWatcher {
96134
return [y, o].join(os.EOL);
97135
}
98136

137+
private async isValidJpsPath(jdkPath: string): Promise<boolean> {
138+
try {
139+
// Check if path exists
140+
await fs.promises.access(jdkPath, fs.constants.R_OK);
141+
142+
// Check if the jps tool exists in the bin directory
143+
const jpsPath = path.join(jdkPath, "bin", "jps" + (os.platform() === 'win32' ? '.exe' : ''));
144+
await fs.promises.access(jpsPath, fs.constants.X_OK);
145+
146+
return true;
147+
} catch (err) {
148+
return false;
149+
}
150+
}
151+
99152
private onDidJdtlsCrash(lastHeartbeat?: string) {
100153
sendInfo("", {
101154
name: "jdtls-last-heartbeat",

0 commit comments

Comments
 (0)