From e3e1b7f6af627204c3b5706e247f30dc5aa4ab8f Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Thu, 9 Apr 2020 11:23:56 +0800 Subject: [PATCH 1/3] Show a warning message about the Unsupported JDK error Signed-off-by: Jinbo Wang --- Troubleshooting.md | 12 ++++++++++ src/anchor.ts | 1 + src/commands.ts | 2 ++ src/configurationProvider.ts | 44 ++++++++++++++++++------------------ src/languageServerPlugin.ts | 4 ++++ src/launchCommand.ts | 40 ++++++++++++++++++++++++++------ 6 files changed, 74 insertions(+), 29 deletions(-) diff --git a/Troubleshooting.md b/Troubleshooting.md index 538eefc4..cc58edf3 100644 --- a/Troubleshooting.md +++ b/Troubleshooting.md @@ -51,6 +51,18 @@ 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 +### Reason: +The runtime JDK doesn't support the compiled classes. One possible reason is your runtime JDK is the latest JDK and the extension doesn't catch up the support yet. Below is a sample error message. +``` +java.lang.UnsupportedClassVersionError: Main (class file version 57.65535) was compiled with preview features that are unsupported. This version of the Java Runtime only recognizes preview features for class file version 58.65535 +``` + +### Try: +1. Install a lower version JDK and reopen your VS Code workspace. +2. Click **F1** -> **Java: Force Java compilation** -> **Full** to rebuild the workspace. +3. 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. diff --git a/src/anchor.ts b/src/anchor.ts index 807567e0..22e2d195 100644 --- a/src/anchor.ts +++ b/src/anchor.ts @@ -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"; diff --git a/src/commands.ts b/src/commands.ts index 7ffa3d4d..5710a0da 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -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); } diff --git a/src/configurationProvider.ts b/src/configurationProvider.ts index bd6aec2b..5c0e08d3 100644 --- a/src/configurationProvider.ts +++ b/src/configurationProvider.ts @@ -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; diff --git a/src/languageServerPlugin.ts b/src/languageServerPlugin.ts index bc7021b8..1ba21f14 100644 --- a/src/languageServerPlugin.ts +++ b/src/languageServerPlugin.ts @@ -100,3 +100,7 @@ export async function isOnClasspath(uri: string): Promise { 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); +} diff --git a/src/launchCommand.ts b/src/launchCommand.ts index 15971a6a..df6325f1 100644 --- a/src/launchCommand.ts +++ b/src/launchCommand.ts @@ -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,26 @@ 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: `This extension currently only supports JDK ${latestSupportedVersion} and below, ` + + `but your application will be running in JDK ${runtimeVersion}, ` + + "it may throw UnsupportedClassVersionError. Please install a lower JDK and try again.", + anchor: UNSUPPORTED_CLASS_VERSION_ERROR, + }); + } + } + } catch (err) { + // do nothing + } +} + function checkJavaVersion(javaExec: string): Promise { return new Promise((resolve, reject) => { cp.execFile(javaExec, ["-version"], {}, (error, stdout, stderr) => { @@ -31,24 +52,29 @@ function checkJavaVersion(javaExec: string): Promise { } 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; } From 8d8b9833285a58dac434ffe85606c43e912bbe82 Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Fri, 10 Apr 2020 15:25:32 +0800 Subject: [PATCH 2/3] adjust the description Signed-off-by: Jinbo Wang --- Troubleshooting.md | 18 +++++++++++------- src/launchCommand.ts | 4 +--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Troubleshooting.md b/Troubleshooting.md index cc58edf3..72c9604e 100644 --- a/Troubleshooting.md +++ b/Troubleshooting.md @@ -52,16 +52,20 @@ This error indicates your application attempts to reference some classes which a 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. + +![image](https://user-images.githubusercontent.com/14052197/78854443-ed47c780-7a53-11ea-8317-d8b097dfba99.png) + +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 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. + ### Reason: -The runtime JDK doesn't support the compiled classes. One possible reason is your runtime JDK is the latest JDK and the extension doesn't catch up the support yet. Below is a sample error message. -``` -java.lang.UnsupportedClassVersionError: Main (class file version 57.65535) was compiled with preview features that are unsupported. This version of the Java Runtime only recognizes preview features for class file version 58.65535 -``` +The compiled classes are not compatible with the runtime JDK. One possible reason is your runtime JDK is the latest JDK and the upstream [Language Support for Java](https://marketplace.visualstudio.com/items?itemName=redhat.java) extension doesn't catch up the support yet. ### Try: -1. Install a lower version JDK and reopen your VS Code workspace. -2. Click **F1** -> **Java: Force Java compilation** -> **Full** to rebuild the workspace. -3. If it still doesn't work, then try **F1** -> **Java: Clean the Java language server workspace** to clean the cache. +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: diff --git a/src/launchCommand.ts b/src/launchCommand.ts index df6325f1..ac129d3f 100644 --- a/src/launchCommand.ts +++ b/src/launchCommand.ts @@ -30,9 +30,7 @@ export async function validateRuntime(config: vscode.DebugConfiguration) { const runtimeVersion = await checkJavaVersion(config.javaExec || path.join(await getJavaHome(), "bin", "java")); if (latestSupportedVersion < runtimeVersion) { showWarningMessageWithTroubleshooting({ - message: `This extension currently only supports JDK ${latestSupportedVersion} and below, ` - + `but your application will be running in JDK ${runtimeVersion}, ` - + "it may throw UnsupportedClassVersionError. Please install a lower JDK and try again.", + 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, }); } From f1be07dd361d102acb69c4f8d99a1054b9dbb363 Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Fri, 10 Apr 2020 15:34:48 +0800 Subject: [PATCH 3/3] Improve troubleshooting description Signed-off-by: Jinbo Wang --- Troubleshooting.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Troubleshooting.md b/Troubleshooting.md index 72c9604e..34c8e534 100644 --- a/Troubleshooting.md +++ b/Troubleshooting.md @@ -56,10 +56,14 @@ Below is a typical error message. ![image](https://user-images.githubusercontent.com/14052197/78854443-ed47c780-7a53-11ea-8317-d8b097dfba99.png) -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 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. - ### Reason: -The compiled classes are not compatible with the runtime JDK. One possible reason is your runtime JDK is the latest JDK and the upstream [Language Support for Java](https://marketplace.visualstudio.com/items?itemName=redhat.java) extension doesn't catch up the support yet. +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.