-
Notifications
You must be signed in to change notification settings - Fork 413
Expand file tree
/
Copy pathjdwp-wrapper.js
More file actions
130 lines (110 loc) · 4.29 KB
/
jdwp-wrapper.js
File metadata and controls
130 lines (110 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env node
/**
* JDWP Port Listener and Communication Wrapper
*
* This script wraps Java process execution and captures the JDWP port
* from the JVM output, then writes it to the endpoint file for VS Code
* to pick up and attach the debugger.
*
* JDWP Output Format:
* "Listening for transport dt_socket at address: 12345"
*/
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
// Get environment variables
const endpointFile = process.env.JDWP_ADAPTER_ENDPOINTS || process.env.VSCODE_JDWP_ADAPTER_ENDPOINTS;
const javaToolOptions = process.env.JAVA_TOOL_OPTIONS || '';
// Check if debugging is enabled
const isDebugEnabled = javaToolOptions.includes('jdwp') && endpointFile;
// Helper function to find java command
function getJavaCommand() {
// Priority 1: Try JAVA_HOME environment variable first (user's explicit choice)
const javaHome = process.env.JAVA_HOME;
if (javaHome) {
const javaPath = path.join(javaHome, 'bin', 'java');
const javaPathExe = process.platform === 'win32' ? `${javaPath}.exe` : javaPath;
// Check if the file exists
if (fs.existsSync(javaPathExe)) {
return javaPath;
}
if (fs.existsSync(javaPath)) {
return javaPath;
}
console.warn(`[Java Debug] JAVA_HOME is set to '${javaHome}', but java command not found there. Falling back to VS Code's Java.`);
}
// Priority 2: Use VSCODE_JAVA_EXEC if provided by VS Code (from Java Language Server)
const vscodeJavaExec = process.env.VSCODE_JAVA_EXEC;
if (vscodeJavaExec && fs.existsSync(vscodeJavaExec)) {
return vscodeJavaExec;
}
// Priority 3: Fall back to 'java' in PATH
return 'java';
}
const javaCmd = getJavaCommand();
if (!isDebugEnabled) {
// No debugging, just run java normally
const child = spawn(javaCmd, process.argv.slice(2), {
stdio: 'inherit',
shell: false
});
child.on('exit', (code) => process.exit(code || 0));
child.on('error', (err) => {
console.error(`[Java Debug] Failed to start java: ${err.message}`);
console.error(`[Java Debug] Make sure Java is installed and either JAVA_HOME is set correctly or 'java' is in your PATH.`);
process.exit(1);
});
} else {
// Debugging enabled, capture JDWP port
const child = spawn(javaCmd, process.argv.slice(2), {
stdio: ['inherit', 'pipe', 'pipe'],
shell: false
});
let portCaptured = false;
const jdwpPortRegex = /Listening for transport dt_socket at address:\s*(\d+)/;
// Shared function to capture JDWP port from output
const capturePort = (output) => {
if (portCaptured) return;
const match = output.match(jdwpPortRegex);
if (match && match[1]) {
const port = parseInt(match[1], 10);
// Validate port range
if (port < 1 || port > 65535) {
console.error(`[Java Debug] Invalid port number: ${port}`);
return;
}
console.log(`[Java Debug] Captured JDWP port: ${port}`);
// Write port to endpoint file
const endpointData = JSON.stringify({
client: {
host: 'localhost',
port: port
}
});
try {
fs.writeFileSync(endpointFile, endpointData, 'utf8');
console.log(`[Java Debug] Wrote endpoint file: ${endpointFile}`);
portCaptured = true;
} catch (err) {
console.error(`[Java Debug] Failed to write endpoint file: ${err}`);
}
}
};
// Monitor stdout for JDWP port
child.stdout.on('data', (data) => {
const output = data.toString();
process.stdout.write(data);
capturePort(output);
});
// Monitor stderr for JDWP port (it might appear on stderr)
child.stderr.on('data', (data) => {
const output = data.toString();
process.stderr.write(data);
capturePort(output);
});
child.on('exit', (code) => process.exit(code || 0));
child.on('error', (err) => {
console.error(`[Java Debug] Failed to start java: ${err}`);
process.exit(1);
});
}