Add a troubleshooting page for the frequently asked errors (#341)

* Add a troubleshooting page for the frequently asked errors

* Update the wrong link and remove the unnecessary separator

* Update Troubleshooting.md

* Make tslint happy

* Refine the words per review

* Add the missing items parameter for showErrorMessage function

* Log the troubleshooting usage

* Add a reference in README to link to troubleshooting page

* Update the fix steps for illegal request type error

* Refine the description words for differnt errors

* Add jdk troubleshooting item

* Add a link to submit an issue

* Add compilation as a try step for ClassNotFoundException

* Add the missing license header

* Resolve the review comments for troubleshooting doc

* Extract dup code to a helper function

* Merge activation event to usage data

* Refactor showMessage utility method

* Add opn to dependency list

* update package-lock.json
This commit is contained in:
Jinbo Wang 2018-08-01 14:35:48 +08:00 committed by GitHub
parent 205e38797a
commit 0e86ed2cc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 300 additions and 75 deletions

View File

@ -91,6 +91,9 @@ Please also check the documentation of [Language Support for Java by Red Hat](ht
- `java.debug.settings.maxStringLength`: the maximum length of string displayed in "Variables" or "Debug Console" viewlet, the string longer than this length will be trimmed, defaults to `0` which means no trim is performed.
- `java.debug.settings.enableHotCodeReplace`: enable hot code replace for Java code. Make sure the auto build is not disabled for [VSCode Java](https://github.com/redhat-developer/vscode-java). See the [wiki page](https://github.com/Microsoft/vscode-java-debug/wiki/Hot-Code-Replace) for more information about usages and limitations.
## Troubleshooting
Reference the [troubleshooting guide](https://github.com/Microsoft/vscode-java-debug/blob/master/Troubleshooting.md) for common errors.
## Feedback and Questions
You can find the full list of issues at [Issue Tracker](https://github.com/Microsoft/vscode-java-debug/issues). You can submit a [bug or feature suggestion](https://github.com/Microsoft/vscode-java-debug/issues/new), and participate community driven [![Gitter](https://badges.gitter.im/Microsoft/vscode-java-debug.svg)](https://gitter.im/Microsoft/vscode-java-debug)

85
Troubleshooting.md Normal file
View File

@ -0,0 +1,85 @@
# Troubleshooting
This document provides the information needed to troubleshoot common errors of Debugger for Java (the debugger). If it does not cover the problem you are seeing, please [log an issue](https://github.com/Microsoft/vscode-java-debug/issues) instead.
## Java Language Support extension fails to start.
The debugger works with [Language Support for Java(TM) by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) (the language server) for source mapping and project support. If the language server fails to start, the debugger will not work as expected. Here is a simple way to check whether the language server is started. Open a .java or a Java project folder in VS Code, and then check the icon at the right side of the status bar. You should see the 👍 icon if the language server is loaded correctly.
![status indicator](https://raw.githubusercontent.com/redhat-developer/vscode-java/master/images/statusMarker.png).
### Try:
1. If you get the error *"The JAVA_HOME environment variable points to a missing folder"* or *"Java runtime could not be located"*, please make sure that the environment variable JAVA_HOME points to a valid JDK. Otherwise, ignore this step.
2. Run VS Code command *"Java: Update project configuration"* to force the language server to reload the current project.
3. Try cleaning the stale workspace cache. Quit all VS Code processes and clean the following cache directory:
- Windows : %APPDATA%\Code\User\workspaceStorage\
- MacOS : $HOME/Library/Application Support/Code/User/workspaceStorage/
- Linux : $HOME/.config/Code/User/workspaceStorage/
4. Try more [troubleshooting guide](https://github.com/redhat-developer/vscode-java/wiki/Troubleshooting) from the language server product site.
## Failed to resolve classpath:
### Reason:
In launch mode, the debugger resolves the classpaths automatically based on the given `mainClass` and `projectName`. It looks for the class specified by `mainClass` as the entry point for launching an application. If there are multiple classes with the same name in the current workspace, the debugger uses the one inside the project specified by `projectName`.
### Try:
1. Check whether the class name specified in `mainClass` exists and is in the right form. The debugger only works with fully qualified class names, e.g. `org.microsoft.app.Main`.
2. Check whether the `projectName` is correct. The actual project name is not always the same to the folder name you see in the File Explorer. Please check the value specified by `projectDescription/name` in the *.project* file, or the `artificatId` in the *pom.xml* for maven project, or the folder name for gradle project.
3. If the problem persists, please try to use the debugger to regenerate the debug configurations in *launch.json*. Remove the existing *launch.json* file and press F5. The debugger will automatically generate a new *launch.json* with the right debug configurations.
## Request type "xyz" is not supported. Only "launch" and "attach" are supported.
### Reason:
The value specified in `request` option of *launch.json* is incorrect.
### Try:
1. Reference the VS Code official document [launch configurations](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) about how to configure *launch.json*.
2. Try to use the debugger to regenerate the debug configurations in *launch.json*. Remove the existing *launch.json* file and press F5. The debugger will automatically generate a new *launch.json* with the right debug configurations.
## 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.
### Try:
1. Restart your application to apply the new changes. Or ignore the message, and continue to debug.
2. You can disable the hot code replace feature by changing the user setting `"java.debug.settings.enableHotCodeReplace": false`.
## Please specify the host name and the port of the remote debuggee in the launch.json.
### Reason:
This error indicates you are debugging a remote Java application. The reason is that you don't configure the remote machine's host name and debug port correctly.
### Try:
1. Check whether the remote Java application is launched in debug mode. The typical command to enable debug mode is like *"java -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n -classpath \<classpath list\> MyMainClass"*, where the parameter *"address=5005"* represents the target JVM exposes *5005* as the debug port.
2. Check the debug port is not blocked by the remote machine's firewall.
## Failed to evaluate. Reason: Cannot evaluate because the thread is resumed.
### Reason:
There are two possible reasons for this error.
- Reason 1: you try to evaluate an expression when the target thread is running. Evaluation only works when your program is on suspend, for example, stopping at a breakpoint or stepping in/out/over.
- Reason 2: you take the VS Code DEBUG CONSOLE view for program input by mistake. DEBUG CONSOLE only accepts input for evaluation, not for program console input.
### Try:
1. For Reason 1, try to add a breakpoint and stop your program there, then evaluate the expression.
2. For Reason 2, try to change the `console` option in the *launch.json* to `externalTerminal` or `integratedTerminal`. This is the official solution for program console input.
## The DEBUG CONSOLE throws Error: Could not find or load main class xyz
### Reason:
You configure the incorrect main class name in `mainClass` of *launch.json*.
### Try:
1. Check whether the class name specified in `mainClass` exists and is in the right form.
2. If the problem persists, it's probably because the language server doesn't load your project correctly. Please reference *"Java Language Support extension fails to start"* paragraph for more troubleshooting info.
## The DEBUG CONSOLE throws ClassNotFoundException
### Reason:
This error indicates your application attempts to reference some classes which are not found in the entire classpaths.
### Try:
1. Check whether you configure the required libraries in the dependency settings file (e.g. *pom.xml*).
2. Run VS Code command *"Java: Force Java compilation"* to force the language server to rebuild the current project.
3. If the problem persists, it's probably because the language server doesn't load your project correctly. Please reference *"Java Language Support extension fails to start"* paragraph for more troubleshooting info.
## Cannot find a class with the main method
### Reason:
When the `mainClass` is unconfigured in the *launch.json*, the debugger will resolve a class with main method automatically. This error indicates the debugger doesn't find any main class in the whole workspace.
### Try:
1. Check at least one main class exists in your workspace.
2. If no main class exists, please create a main class first. Otherwise, it's probably because the language server fails to start. Please reference *"Java Language Support extension fails to start"* paragraph for more troubleshooting info.

13
package-lock.json generated
View File

@ -1742,6 +1742,11 @@
"integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=",
"dev": true
},
"is-wsl": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
"integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@ -2301,6 +2306,14 @@
"wrappy": "1"
}
},
"opn": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
"integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==",
"requires": {
"is-wsl": "1.1.0"
}
},
"orchestrator": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz",

View File

@ -384,6 +384,7 @@
"vscode": "^1.1.6"
},
"dependencies": {
"opn": "^5.3.0",
"vscode-extension-telemetry": "0.0.18"
}
}

View File

@ -2,12 +2,13 @@
// Licensed under the MIT license.
import * as vscode from "vscode";
import TelemetryReporter from "vscode-extension-telemetry";
import * as commands from "./commands";
import { logger, Type } from "./logger";
import * as utility from "./utility";
export class JavaDebugConfigurationProvider implements vscode.DebugConfigurationProvider {
private isUserSettingsDirty: boolean = true;
constructor(private _reporter: TelemetryReporter) {
constructor() {
vscode.workspace.onDidChangeConfiguration((event) => {
if (vscode.debug.activeDebugSession) {
this.isUserSettingsDirty = false;
@ -132,25 +133,28 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
config.classPaths = result[1];
}
if (this.isEmptyArray(config.classPaths) && this.isEmptyArray(config.modulePaths)) {
const hintMessage = "Cannot resolve the modulepaths/classpaths automatically, please specify the value in the launch.json.";
vscode.window.showErrorMessage(hintMessage);
this.log("usageError", hintMessage);
utility.showErrorMessageWithTroubleshooting({
message: "Cannot resolve the modulepaths/classpaths automatically, please specify the value in the launch.json.",
type: Type.USAGEERROR,
});
return undefined;
}
} else if (config.request === "attach") {
if (!config.hostName || !config.port) {
vscode.window.showErrorMessage("Please specify the host name and the port of the remote debuggee in the launch.json.");
this.log("usageError", "Please specify the host name and the port of the remote debuggee in the launch.json.");
utility.showErrorMessageWithTroubleshooting({
message: "Please specify the host name and the port of the remote debuggee in the launch.json.",
type: Type.USAGEERROR,
});
return undefined;
}
} else {
const ans = await vscode.window.showErrorMessage(
// tslint:disable-next-line:max-line-length
"Request type \"" + config.request + "\" is not supported. Only \"launch\" and \"attach\" are supported.", "Open launch.json");
const ans = await utility.showErrorMessageWithTroubleshooting({
message: `Request type "${config.request}" is not supported. Only "launch" and "attach" are supported.`,
type: Type.USAGEERROR,
}, "Open launch.json");
if (ans === "Open launch.json") {
await vscode.commands.executeCommand(commands.VSCODE_ADD_DEBUGCONFIGURATION);
}
this.log("usageError", "Illegal request type in launch.json");
return undefined;
}
const debugServerPort = await startDebugSession();
@ -158,40 +162,35 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
config.debugServer = debugServerPort;
return config;
} else {
this.log("exception", "Failed to start debug server.");
logger.logMessage(Type.EXCEPTION, "Failed to start debug server.");
// Information for diagnostic:
console.log("Cannot find a port for debugging session");
return undefined;
}
} catch (ex) {
const errorMessage = (ex && ex.message) || ex;
vscode.window.showErrorMessage(String(errorMessage));
if (this._reporter) {
const exception = (ex && ex.data && ex.data.cause)
|| { stackTrace: [], detailMessage: String((ex && ex.message) || ex || "Unknown exception") };
const properties = {
message: "",
stackTrace: "",
};
if (exception && typeof exception === "object") {
properties.message = exception.detailMessage;
properties.stackTrace = (Array.isArray(exception.stackTrace) && JSON.stringify(exception.stackTrace))
|| String(exception.stackTrace);
} else {
properties.message = String(exception);
}
this._reporter.sendTelemetryEvent("exception", properties);
const exception = (ex && ex.data && ex.data.cause)
|| { stackTrace: [], detailMessage: String((ex && ex.message) || ex || "Unknown exception") };
const properties = {
message: "",
stackTrace: "",
};
if (exception && typeof exception === "object") {
properties.message = exception.detailMessage;
properties.stackTrace = (Array.isArray(exception.stackTrace) && JSON.stringify(exception.stackTrace))
|| String(exception.stackTrace);
} else {
properties.message = String(exception);
}
utility.showErrorMessageWithTroubleshooting({
message: String(errorMessage),
type: Type.EXCEPTION,
details: properties,
});
return undefined;
}
}
private log(type: string, message: string) {
if (this._reporter) {
this._reporter.sendTelemetryEvent(type, { message });
}
}
private isEmptyArray(configItems: any): boolean {
return !Array.isArray(configItems) || !configItems.length;
}
@ -199,8 +198,10 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
private async chooseMainClass(folder: vscode.WorkspaceFolder | undefined): Promise<IMainClassOption | undefined> {
const res = await resolveMainClass(folder ? folder.uri : undefined);
if (res.length === 0) {
vscode.window.showErrorMessage(
"Cannot find a class with the main method.");
utility.showErrorMessageWithTroubleshooting({
message: "Cannot find a class with the main method.",
type: Type.USAGEERROR,
});
return undefined;
}
const pickItems = res.map((item) => {

View File

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
export const JAVA_LANGID: string = "java";
export const HCR_EVENT = "hotcodereplace";
export const USER_NOTIFICATION_EVENT = "usernotification";

View File

@ -3,49 +3,41 @@
import * as path from "path";
import * as vscode from "vscode";
import TelemetryReporter from "vscode-extension-telemetry";
import * as commands from "./commands";
import { JavaDebugConfigurationProvider } from "./configurationProvider";
import { HCR_EVENT, JAVA_LANGID, USER_NOTIFICATION_EVENT } from "./constants";
import { handleHotCodeReplaceCustomEvent, initializeHotCodeReplace } from "./hotCodeReplace";
import { logger, Type } from "./logger";
import * as utility from "./utility";
export function activate(context: vscode.ExtensionContext) {
// The reporter will be initialized by the later telemetry handler.
let reporter: TelemetryReporter = null;
logger.initialize(context);
logger.log(Type.ACTIVATEEXTENSION, {}); // TODO: Activation belongs to usage data, remove this line.
logger.log(Type.USAGEDATA, {
description: "activateExtension",
});
// Telemetry.
const extensionPackage = require(context.asAbsolutePath("./package.json"));
if (extensionPackage) {
const packageInfo = {
name: extensionPackage.name,
version: extensionPackage.version,
aiKey: extensionPackage.aiKey,
};
if (packageInfo.aiKey) {
reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
reporter.sendTelemetryEvent("activateExtension", {});
const measureKeys = ["duration"];
vscode.debug.onDidTerminateDebugSession(() => {
fetchUsageData().then((ret) => {
if (Array.isArray(ret) && ret.length) {
ret.forEach((entry) => {
const commonProperties: any = {};
const measureProperties: any = {};
for (const key of Object.keys(entry)) {
if (measureKeys.indexOf(key) >= 0) {
measureProperties[key] = entry[key];
} else {
commonProperties[key] = String(entry[key]);
}
}
reporter.sendTelemetryEvent(entry.scope === "exception" ? "exception" : "usageData", commonProperties, measureProperties);
});
const measureKeys = ["duration"];
vscode.debug.onDidTerminateDebugSession(() => {
fetchUsageData().then((ret) => {
if (Array.isArray(ret) && ret.length) {
ret.forEach((entry) => {
const commonProperties: any = {};
const measureProperties: any = {};
for (const key of Object.keys(entry)) {
if (measureKeys.indexOf(key) >= 0) {
measureProperties[key] = entry[key];
} else {
commonProperties[key] = String(entry[key]);
}
}
logger.log(entry.scope === "exception" ? Type.EXCEPTION : Type.USAGEDATA, commonProperties, measureProperties);
});
});
}
}
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider("java", new JavaDebugConfigurationProvider(reporter)));
}
});
});
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider("java", new JavaDebugConfigurationProvider()));
context.subscriptions.push(vscode.commands.registerCommand("JavaDebug.SpecifyProgramArgs", async () => {
return specifyProgramArguments(context);
}));
@ -69,9 +61,13 @@ export function deactivate() {
function handleUserNotification(customEvent) {
if (customEvent.body.notificationType === "ERROR") {
vscode.window.showErrorMessage(customEvent.body.message);
utility.showErrorMessageWithTroubleshooting({
message: customEvent.body.message,
});
} else if (customEvent.body.notificationType === "WARNING") {
vscode.window.showWarningMessage(customEvent.body.message);
utility.showWarningMessageWithTroubleshooting({
message: customEvent.body.message,
});
} else {
vscode.window.showInformationMessage(customEvent.body.message);
}

View File

@ -4,6 +4,7 @@
import * as vscode from "vscode";
import { HCR_EVENT, JAVA_LANGID } from "./constants";
import * as utility from "./utility";
const suppressedReasons: Set<string> = new Set();
@ -40,9 +41,9 @@ export function handleHotCodeReplaceCustomEvent(hcrEvent) {
if (hcrEvent.body.changeType === HcrChangeType.ERROR || hcrEvent.body.changeType === HcrChangeType.WARNING) {
if (!suppressedReasons.has(hcrEvent.body.message)) {
vscode.window.showInformationMessage(
`Hot code replace failed - ${hcrEvent.body.message}. Would you like to restart the debug session?`,
YES_BUTTON, NO_BUTTON, NEVER_BUTTON).then((res) => {
utility.showWarningMessageWithTroubleshooting({
message: `Hot code replace failed - ${hcrEvent.body.message}. Would you like to restart the debug session?`,
}, YES_BUTTON, NO_BUTTON, NEVER_BUTTON).then((res) => {
if (res === NEVER_BUTTON) {
suppressedReasons.add(hcrEvent.body.message);
} else if (res === YES_BUTTON) {

48
src/logger.ts Normal file
View File

@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as vscode from "vscode";
import TelemetryReporter from "vscode-extension-telemetry";
export enum Type {
EXCEPTION = "exception",
USAGEDATA = "usageData",
USAGEERROR = "usageError",
ACTIVATEEXTENSION = "activateExtension", // TODO: Activation belongs to usage data, remove this category.
}
class Logger {
private reporter: TelemetryReporter = null;
public initialize(context: vscode.ExtensionContext): void {
if (this.reporter) {
return;
}
const extensionPackage = require(context.asAbsolutePath("./package.json"));
if (extensionPackage) {
const packageInfo = {
name: extensionPackage.name,
version: extensionPackage.version,
aiKey: extensionPackage.aiKey,
};
if (packageInfo.aiKey) {
this.reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
}
}
}
public log(type: Type, properties?: { [key: string]: string; }, measures?: { [key: string]: number; }): void {
if (!this.reporter) {
return;
}
this.reporter.sendTelemetryEvent(type, properties, measures);
}
public logMessage(type: Type, message: string): void {
this.log(type, { message });
}
}
export const logger = new Logger();

74
src/utility.ts Normal file
View File

@ -0,0 +1,74 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as opn from "opn";
import * as vscode from "vscode";
import { logger, Type } from "./logger";
const TROUBLESHOOTING_LINK = "https://github.com/Microsoft/vscode-java-debug/blob/master/Troubleshooting.md";
const LEARN_MORE = "Learn More";
interface IMessage {
message: string;
type?: Type;
details?: { [key: string]: string; };
}
function logMessage(message: IMessage): void {
if (!message.type) {
return;
}
if (message.details) {
logger.log(message.type, message.details);
} else {
logger.logMessage(message.type, message.message);
}
}
export async function showInformationMessage(message: IMessage, ...items: string[]): Promise<string | undefined> {
logMessage(message);
return await vscode.window.showInformationMessage(message.message, ...items);
}
export async function showWarningMessage(message: IMessage, ...items: string[]): Promise<string | undefined> {
logMessage(message);
return await vscode.window.showWarningMessage(message.message, ...items);
}
export async function showErrorMessage(message: IMessage, ...items: string[]): Promise<string | undefined> {
logMessage(message);
return await vscode.window.showErrorMessage(message.message, ...items);
}
export async function showInformationMessageWithTroubleshooting(message: IMessage, ...items: string[]): Promise<string | undefined> {
const choice = await showInformationMessage(message, ...items, LEARN_MORE);
return handleTroubleshooting(choice, message.message);
}
export async function showWarningMessageWithTroubleshooting(message: IMessage, ...items: string[]): Promise<string | undefined> {
const choice = await showWarningMessage(message, ...items, LEARN_MORE);
return handleTroubleshooting(choice, message.message);
}
export async function showErrorMessageWithTroubleshooting(message: IMessage, ...items: string[]): Promise<string | undefined> {
const choice = await showErrorMessage(message, ...items, LEARN_MORE);
return handleTroubleshooting(choice, message.message);
}
function openLink(url: string): void {
opn(url);
}
function handleTroubleshooting(choice: string, message: string): string | undefined {
if (choice === LEARN_MORE) {
openLink(TROUBLESHOOTING_LINK);
logger.log(Type.USAGEDATA, {
troubleshooting: "yes",
troubleshootingMessage: message,
});
return;
}
return choice;
}