8000 Show a warning message about the Unsupported JDK error by testforstephen · Pull Request #790 · microsoft/vscode-java-debug · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

![image](https://user-images.githubusercontent.com/14052197/78854443-ed47c780-7a53-11ea-8317-d8b097dfba99.png)

### 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.
Expand Down
1 change: 1 addition & 0 deletions src/anchor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
2 changes: 2 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
44 changes: 22 additions & 22 deletions src/configurationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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({
Expand All @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions src/languageServerPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
38 changes: 31 additions & 7 deletions src/launchCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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) => {
Expand All @@ -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;
}

Expand Down
0