Show a warning message about the Unsupported JDK error (#790)
* Show a warning message about the Unsupported JDK error Signed-off-by: Jinbo Wang <jinbwan@microsoft.com> * adjust the description Signed-off-by: Jinbo Wang <jinbwan@microsoft.com> * Improve troubleshooting description Signed-off-by: Jinbo Wang <jinbwan@microsoft.com>
This commit is contained in:
parent
6b52079ce4
commit
656beaab8f
|
@ -51,6 +51,26 @@ This error indicates your application attempts to reference some classes which a
|
|||
3. Run VS Code command *"Java: Force Java compilation"* to force the language server to rebuild the current project.
|
||||
4. If the problem persists, it's probably because the language server doesn't load your project correctly. Please reference the [language server troubleshooting](#try) paragraph for more troubleshooting info.
|
||||
|
||||
## Program throws UnsupportedClassVersionError
|
||||
Below is a typical error message.
|
||||
|
||||

|
||||
|
||||
### Reason:
|
||||
The compiled classes are not compatible with the runtime JDK.
|
||||
|
||||
The class file version `57.65535` stands for Java 13 preview, where the major version `57` stands for Java 13, the minor version `65535` stands for preview feature. Similarly `58.65535` stands for Java 14 preview.
|
||||
|
||||
The error says the compiled class is `57.65535`, but the runtime JDK only recognizes class file versoin `58.65535`. That's because the preview feature is not backward compatible, i.e. JVM 14 doesn't support 13 preview feature. The [openjdk](https://openjdk.java.net/jeps/12) website has claimed the reason that it would be costly for JDK 14 to support preview features from JDK 13 which were changed or dropped in response to feedback.
|
||||
|
||||
One possible root cause for this error is your runtime JDK is the latest JDK but the upstream [Language Support for Java](https://marketplace.visualstudio.com/items?itemName=redhat.java) extension doesn't catch up the support yet.
|
||||
|
||||
### Try:
|
||||
1. Try to update [Language Support for Java](https://marketplace.visualstudio.com/items?itemName=redhat.java) to the latest, and then try step 3 to rebuild the workspace.
|
||||
2. If it doesn't work, then try to install an older JDK version, set its installation folder to "java.home" user setting in _.vscode/settings.json_ and reopen your VS Code workspace.
|
||||
3. Click **F1** -> **Java: Force Java compilation** -> **Full** to rebuild the workspace.
|
||||
4. If it still doesn't work, then try **F1** -> **Java: Clean the Java language server workspace** to clean the cache.
|
||||
|
||||
## Failed to complete hot code replace:
|
||||
### Reason:
|
||||
This error indicates you are doing `Hot Code Replace`. The `Hot Code Replace` feature depends on the underlying JVM implementation. If you get this error, that indicates the new changes cannot be hot replaced by JVM.
|
||||
|
|
|
@ -7,3 +7,4 @@ export const ATTACH_CONFIG_ERROR = "please-specify-the-host-name-and-the-port-of
|
|||
export const EVALUATE_ON_RUNNING_THREAD = "failed-to-evaluate-reason-cannot-evaluate-because-the-thread-is-resumed";
|
||||
export const CANNOT_FIND_MAIN_CLASS = "cannot-find-a-class-with-the-main-method";
|
||||
export const BUILD_FAILED = "build-failed-do-you-want-to-continue";
|
||||
export const UNSUPPORTED_CLASS_VERSION_ERROR = "program-throws-unsupportedclassversionerror";
|
||||
|
|
|
@ -38,6 +38,8 @@ export const JAVA_IS_ON_CLASSPATH = "vscode.java.isOnClasspath";
|
|||
|
||||
export const JAVA_RESOLVE_JAVAEXECUTABLE = "vscode.java.resolveJavaExecutable";
|
||||
|
||||
export const JAVA_FETCH_PLATFORM_SETTINGS = "vscode.java.fetchPlatformSettings";
|
||||
|
||||
export function executeJavaLanguageServerCommand(...rest) {
|
||||
return executeJavaExtensionCommand(JAVA_EXECUTE_WORKSPACE_COMMAND, ...rest);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import * as anchor from "./anchor";
|
|||
import { buildWorkspace } from "./build";
|
||||
import * as commands from "./commands";
|
||||
import * as lsPlugin from "./languageServerPlugin";
|
||||
import { detectLaunchCommandStyle } from "./launchCommand";
|
||||
import { detectLaunchCommandStyle, validateRuntime } from "./launchCommand";
|
||||
import { logger, Type } from "./logger";
|
||||
import * as utility from "./utility";
|
||||
import { VariableResolver } from "./variableResolver";
|
||||
|
@ -207,6 +207,27 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
|
|||
config.javaExec = await lsPlugin.resolveJavaExecutable(config.mainClass, config.projectName);
|
||||
// Add the default launch options to the config.
|
||||
config.cwd = config.cwd || _.get(folder, "uri.fsPath");
|
||||
if (Array.isArray(config.args)) {
|
||||
config.args = this.concatArgs(config.args);
|
||||
}
|
||||
|
||||
if (Array.isArray(config.vmArgs)) {
|
||||
config.vmArgs = this.concatArgs(config.vmArgs);
|
||||
}
|
||||
|
||||
// Auto add '--enable-preview' vmArgs if the java project enables COMPILER_PB_ENABLE_PREVIEW_FEATURES flag.
|
||||
if (await lsPlugin.detectPreviewFlag(config.mainClass, config.projectName)) {
|
||||
config.vmArgs = (config.vmArgs || "") + " --enable-preview";
|
||||
validateRuntime(config);
|
||||
}
|
||||
|
||||
if (!config.shortenCommandLine || config.shortenCommandLine === "auto") {
|
||||
config.shortenCommandLine = await detectLaunchCommandStyle(config);
|
||||
}
|
||||
|
||||
if (process.platform === "win32" && config.console !== "internalConsole") {
|
||||
config.launcherScript = utility.getLauncherScriptPath();
|
||||
}
|
||||
} else if (config.request === "attach") {
|
||||
if (!config.hostName || !config.port) {
|
||||
throw new utility.UserError({
|
||||
|
@ -223,27 +244,6 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
|
|||
});
|
||||
}
|
||||
|
||||
if (Array.isArray(config.args)) {
|
||||
config.args = this.concatArgs(config.args);
|
||||
}
|
||||
|
||||
if (Array.isArray(config.vmArgs)) {
|
||||
config.vmArgs = this.concatArgs(config.vmArgs);
|
||||
}
|
||||
|
||||
// Auto add '--enable-preview' vmArgs if the java project enables COMPILER_PB_ENABLE_PREVIEW_FEATURES flag.
|
||||
if (await lsPlugin.detectPreviewFlag(config.mainClass, config.projectName)) {
|
||||
config.vmArgs = (config.vmArgs || "") + " --enable-preview";
|
||||
}
|
||||
|
||||
if (config.request === "launch" && (!config.shortenCommandLine || config.shortenCommandLine === "auto")) {
|
||||
config.shortenCommandLine = await detectLaunchCommandStyle(config);
|
||||
}
|
||||
|
||||
if (process.platform === "win32" && config.request === "launch" && config.console !== "internalConsole") {
|
||||
config.launcherScript = utility.getLauncherScriptPath();
|
||||
}
|
||||
|
||||
const debugServerPort = await lsPlugin.startDebugSession();
|
||||
if (debugServerPort) {
|
||||
config.debugServer = debugServerPort;
|
||||
|
|
|
@ -100,3 +100,7 @@ export async function isOnClasspath(uri: string): Promise<boolean> {
|
|||
export function resolveJavaExecutable(mainClass, projectName) {
|
||||
return commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_JAVAEXECUTABLE, mainClass, projectName);
|
||||
}
|
||||
|
||||
export function fetchPlatformSettings(): any {
|
||||
return commands.executeJavaLanguageServerCommand(commands.JAVA_FETCH_PLATFORM_SETTINGS);
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ import * as _ from "lodash";
|
|||
import * as path from "path";
|
||||
import * as vscode from "vscode";
|
||||
|
||||
import { inferLaunchCommandLength } from "./languageServerPlugin";
|
||||
import { getJavaHome } from "./utility";
|
||||
import { UNSUPPORTED_CLASS_VERSION_ERROR } from "./anchor";
|
||||
import { fetchPlatformSettings, inferLaunchCommandLength } from "./languageServerPlugin";
|
||||
import { getJavaHome, showWarningMessageWithTroubleshooting } from "./utility";
|
||||
|
||||
enum shortenApproach {
|
||||
none = "none",
|
||||
|
@ -21,6 +22,24 @@ export async function detectLaunchCommandStyle(config: vscode.DebugConfiguration
|
|||
return (await shouldShortenIfNecessary(config)) ? recommendedShortenApproach : shortenApproach.none;
|
||||
}
|
||||
|
||||
export async function validateRuntime(config: vscode.DebugConfiguration) {
|
||||
try {
|
||||
const platformSettings = await fetchPlatformSettings();
|
||||
if (platformSettings && platformSettings.latestSupportedJavaVersion) {
|
||||
const latestSupportedVersion = flattenMajorVersion(platformSettings.latestSupportedJavaVersion);
|
||||
const runtimeVersion = await checkJavaVersion(config.javaExec || path.join(await getJavaHome(), "bin", "java"));
|
||||
if (latestSupportedVersion < runtimeVersion) {
|
||||
showWarningMessageWithTroubleshooting({
|
||||
message: "The compiled classes are not compatible with the runtime JDK. To mitigate the issue, please refer to \"Learn More\".",
|
||||
anchor: UNSUPPORTED_CLASS_VERSION_ERROR,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
function checkJavaVersion(javaExec: string): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
cp.execFile(javaExec, ["-version"], {}, (error, stdout, stderr) => {
|
||||
|
@ -31,24 +50,29 @@ function checkJavaVersion(javaExec: string): Promise<number> {
|
|||
}
|
||||
|
||||
function parseMajorVersion(content: string): number {
|
||||
let regexp = /version "(.*)"/g;
|
||||
let match = regexp.exec(content);
|
||||
const regexp = /version "(.*)"/g;
|
||||
const match = regexp.exec(content);
|
||||
if (!match) {
|
||||
return 0;
|
||||
}
|
||||
let version = match[1];
|
||||
|
||||
return flattenMajorVersion(match[1]);
|
||||
}
|
||||
|
||||
function flattenMajorVersion(version: string): number {
|
||||
// Ignore '1.' prefix for legacy Java versions
|
||||
if (version.startsWith("1.")) {
|
||||
version = version.substring(2);
|
||||
}
|
||||
|
||||
// look into the interesting bits now
|
||||
regexp = /\d+/g;
|
||||
match = regexp.exec(version);
|
||||
const regexp = /\d+/g;
|
||||
const match = regexp.exec(version);
|
||||
let javaVersion = 0;
|
||||
if (match) {
|
||||
javaVersion = parseInt(match[0], 10);
|
||||
}
|
||||
|
||||
return javaVersion;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue