Skip to content

Commit 69d727c

Browse files
committed
[VSCode] Take advantage of CDS
Signed-off-by: BoykoAlex <alex.boyko@broadcom.com>
1 parent 62aa2b4 commit 69d727c

File tree

2 files changed

+71
-4
lines changed

2 files changed

+71
-4
lines changed

vscode-extensions/commons-vscode/src/launch-util.ts

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import * as VSCode from 'vscode';
44
import * as Path from 'path';
55
import * as FS from 'fs';
6+
import * as Crypto from 'crypto';
67
import PortFinder from 'portfinder';
78
import * as Net from 'net';
89
import * as CommonsCommands from './commands';
@@ -25,6 +26,7 @@ const p2c = P2C.createConverter(undefined, false, false);
2526
PortFinder.basePort = 45556;
2627

2728
const LOG_RESOLVE_VM_ARG_PREFIX = '-Xlog:jni+resolve=';
29+
const LOG_AOT_VM_ARG_PREFIX = '-Xlog:aot';
2830
const DEBUG_ARG = '-agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=y';
2931

3032
export interface ActivatorOptions {
@@ -123,6 +125,62 @@ function findJdtEmbeddedJRE(): string | undefined{
123125
}
124126
}
125127

128+
const JAVA_25_VERSION = 25;
129+
130+
function hashString(value: string): string {
131+
return Crypto.createHash('sha256').update(value).digest('hex').substring(0, 12);
132+
}
133+
134+
function getAotCachePath(extensionPath: string, jvm: JVM): string {
135+
const javaHomeHash = hashString(jvm.getJavaHome());
136+
return Path.join(extensionPath, 'language-server', `spring-boot-ls_${javaHomeHash}.aot`);
137+
}
138+
139+
function prepareCdsArgs(options: ActivatorOptions, context: VSCode.ExtensionContext, jvm: JVM): CdsResult {
140+
if (!options.workspaceOptions.get("cds.enabled")) {
141+
return { cdsArgs: [] };
142+
}
143+
144+
if (jvm.getMajorVersion() < JAVA_25_VERSION) {
145+
VSCode.window.showInformationMessage(
146+
'Spring Boot Language Server: CDS is enabled but requires Java 25 or later. ' +
147+
`Current Java version is ${jvm.getMajorVersion()}. Starting without CDS.`
148+
);
149+
return { cdsArgs: [] };
150+
}
151+
152+
const aotCachePath = getAotCachePath(context.extensionPath, jvm);
153+
const cdsArgs: string[] = [];
154+
155+
if (FS.existsSync(aotCachePath)) {
156+
options.clientOptions.outputChannel.appendLine(`CDS: Using existing AOT cache: ${aotCachePath}`);
157+
cdsArgs.push(`-XX:AOTCache=${aotCachePath}`);
158+
} else {
159+
options.clientOptions.outputChannel.appendLine(`CDS: No AOT cache found, will record cache on this run: ${aotCachePath}`);
160+
cdsArgs.push(`-XX:AOTCacheOutput=${aotCachePath}`);
161+
}
162+
163+
cdsArgs.push(`${LOG_AOT_VM_ARG_PREFIX}=off`);
164+
165+
return { cdsArgs };
166+
}
167+
168+
interface CdsResult {
169+
cdsArgs: string[];
170+
}
171+
172+
function addCdsArgs(vmArgs: string[], cdsResult?: CdsResult): void {
173+
if (!cdsResult?.cdsArgs.length) {
174+
return;
175+
}
176+
for (const arg of cdsResult.cdsArgs) {
177+
if (arg.startsWith(LOG_AOT_VM_ARG_PREFIX) && hasVmArg(LOG_AOT_VM_ARG_PREFIX, vmArgs)) {
178+
continue;
179+
}
180+
vmArgs.push(arg);
181+
}
182+
}
183+
126184
export function activate(options: ActivatorOptions, context: VSCode.ExtensionContext): Thenable<LanguageClient> {
127185
if (options.CONNECT_TO_LS) {
128186
return VSCode.window.showInformationMessage("Start language server")
@@ -155,30 +213,33 @@ export function activate(options: ActivatorOptions, context: VSCode.ExtensionCon
155213

156214
clientOptions.outputChannel.appendLine("isJavaEightOrHigher => true");
157215

216+
const cdsResult = prepareCdsArgs(options, context, jvm);
217+
158218
if (process.env['SPRING_LS_USE_SOCKET']) {
159-
return setupLanguageClient(context, createServerOptionsForPortComm(options, context, jvm), options);
219+
return setupLanguageClient(context, createServerOptionsForPortComm(options, context, jvm, cdsResult), options);
160220
} else {
161-
return setupLanguageClient(context, createServerOptions(options, context, jvm), options);
221+
return setupLanguageClient(context, createServerOptions(options, context, jvm, undefined, cdsResult), options);
162222
}
163223
});
164224
}
165225
}
166226

167-
function createServerOptions(options: ActivatorOptions, context: VSCode.ExtensionContext, jvm: JVM, port? : number): Executable {
227+
function createServerOptions(options: ActivatorOptions, context: VSCode.ExtensionContext, jvm: JVM, port?: number, cdsResult?: CdsResult): Executable {
168228
const executable: Executable = Object.create(null);
169229
const execOptions: ExecutableOptions = Object.create(null);
170230
execOptions.env = Object.assign(process.env);
171231
execOptions.cwd = context.extensionPath
172232
executable.options = execOptions;
173233
executable.command = jvm.getJavaExecutable();
174234
const vmArgs = prepareJvmArgs(options, context, jvm, port);
235+
addCdsArgs(vmArgs, cdsResult);
175236
addCpAndLauncherToJvmArgs(vmArgs, options, context);
176237
executable.args = vmArgs;
177238
return executable;
178239

179240
}
180241

181-
function createServerOptionsForPortComm(options: ActivatorOptions, context: VSCode.ExtensionContext, jvm: JVM): ServerOptions {
242+
function createServerOptionsForPortComm(options: ActivatorOptions, context: VSCode.ExtensionContext, jvm: JVM, cdsResult?: CdsResult): ServerOptions {
182243
return () =>
183244
new Promise((resolve) => {
184245
PortFinder.getPort((err, port) => {
@@ -195,6 +256,7 @@ function createServerOptionsForPortComm(options: ActivatorOptions, context: VSCo
195256
cwd: context.extensionPath
196257
};
197258
const args = prepareJvmArgs(options, context, jvm, port);
259+
addCdsArgs(args, cdsResult);
198260
if (options.explodedLsJarData) {
199261
const explodedLsJarData = options.explodedLsJarData;
200262
const lsRoot = Path.resolve(context.extensionPath, explodedLsJarData.lsLocation);

vscode-extensions/vscode-spring-boot/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,11 @@
529529
],
530530
"default": "error",
531531
"description": "Log level for the Spring Boot Language Server"
532+
},
533+
"spring-boot.ls.cds.enabled": {
534+
"type": "boolean",
535+
"default": false,
536+
"description": "Enable Class Data Sharing (AOT Cache) for faster Language Server startup. Requires Java 25 or later."
532537
}
533538
}
534539
},

0 commit comments

Comments
 (0)