Skip to content

Commit 24a7260

Browse files
Use the correct runtime to validate the JVM versions between the debugger and debuggee (#353)
* Use the correct runtime to validate the JVM versions between the debugger and debuggee * Resolve java version from the system library jar
1 parent e514990 commit 24a7260

File tree

4 files changed

+104
-42
lines changed

4 files changed

+104
-42
lines changed

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/ISourceLookUpProvider.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,14 @@ public interface ISourceLookUpProvider extends IProvider {
3030
String getSourceFileURI(String fullyQualifiedName, String sourcePath);
3131

3232
String getSourceContents(String uri);
33+
34+
/**
35+
* Returns the Java runtime that the specified project's build path used.
36+
* @param projectName
37+
* the specified project name
38+
* @return the Java runtime version the specified project used. null if projectName is empty or doesn't exist.
39+
*/
40+
default String getJavaRuntimeVersion(String projectName) {
41+
return null;
42+
}
3343
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AttachRequestHandler.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
import com.microsoft.java.debug.core.protocol.Requests.Command;
4141
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
4242

43+
import org.apache.commons.lang3.StringUtils;
44+
4345
public class AttachRequestHandler implements IDebugRequestHandler {
4446
private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME);
4547
private VMHandler vmHandler = new VMHandler();
@@ -59,28 +61,14 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
5961

6062
IVirtualMachineManagerProvider vmProvider = context.getProvider(IVirtualMachineManagerProvider.class);
6163
vmHandler.setVmProvider(vmProvider);
62-
64+
IDebugSession debugSession = null;
6365
try {
6466
logger.info(String.format("Trying to attach to remote debuggee VM %s:%d .", attachArguments.hostName, attachArguments.port));
65-
IDebugSession debugSession = DebugUtility.attach(vmProvider.getVirtualMachineManager(), attachArguments.hostName, attachArguments.port,
67+
debugSession = DebugUtility.attach(vmProvider.getVirtualMachineManager(), attachArguments.hostName, attachArguments.port,
6668
attachArguments.timeout);
6769
context.setDebugSession(debugSession);
6870
vmHandler.connectVirtualMachine(debugSession.getVM());
6971
logger.info("Attaching to debuggee VM succeeded.");
70-
71-
// If the debugger and debuggee run at the different JVM platforms, show a warning message.
72-
if (debugSession != null) {
73-
String debuggeeVersion = debugSession.getVM().version();
74-
String debuggerVersion = System.getProperty("java.version");
75-
if (!debuggerVersion.equals(debuggeeVersion)) {
76-
String warnMessage = String.format("[Warn] The debugger and the debuggee are running in different versions of JVMs. "
77-
+ "You could see wrong source mapping results.\n"
78-
+ "Debugger JVM version: %s\n"
79-
+ "Debuggee JVM version: %s", debuggerVersion, debuggeeVersion);
80-
logger.warning(warnMessage);
81-
context.getProtocolServer().sendEvent(Events.OutputEvent.createConsoleOutput(warnMessage));
82-
}
83-
}
8472
} catch (IOException | IllegalConnectorArgumentsException e) {
8573
throw AdapterUtils.createCompletionException(
8674
String.format("Failed to attach to remote debuggee VM. Reason: %s", e.toString()),
@@ -96,6 +84,20 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
9684
// TODO: Clean up the initialize mechanism
9785
ISourceLookUpProvider sourceProvider = context.getProvider(ISourceLookUpProvider.class);
9886
sourceProvider.initialize(context, options);
87+
// If the debugger and debuggee run at the different JVM platforms, show a warning message.
88+
if (debugSession != null) {
89+
String debuggeeVersion = debugSession.getVM().version();
90+
String debuggerVersion = sourceProvider.getJavaRuntimeVersion(attachArguments.projectName);
91+
if (StringUtils.isNotBlank(debuggerVersion) && !debuggerVersion.equals(debuggeeVersion)) {
92+
String warnMessage = String.format("[Warn] The debugger and the debuggee are running in different versions of JVMs. "
93+
+ "You could see wrong source mapping results.\n"
94+
+ "Debugger JVM version: %s\n"
95+
+ "Debuggee JVM version: %s", debuggerVersion, debuggeeVersion);
96+
logger.warning(warnMessage);
97+
context.getProtocolServer().sendEvent(Events.OutputEvent.createConsoleOutput(warnMessage));
98+
}
99+
}
100+
99101
IEvaluationProvider evaluationProvider = context.getProvider(IEvaluationProvider.class);
100102
evaluationProvider.initialize(context, options);
101103
IHotCodeReplaceProvider hcrProvider = context.getProvider(IHotCodeReplaceProvider.class);

com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/JdtSourceLookUpProvider.java

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2017 Microsoft Corporation and others.
2+
* Copyright (c) 2017-2020 Microsoft Corporation and others.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -22,28 +22,37 @@
2222
import java.nio.file.Paths;
2323
import java.util.HashMap;
2424
import java.util.Map;
25+
import java.util.jar.Attributes;
26+
import java.util.jar.Manifest;
2527
import java.util.logging.Level;
2628
import java.util.logging.Logger;
2729

30+
import com.microsoft.java.debug.core.Configuration;
31+
import com.microsoft.java.debug.core.DebugException;
32+
import com.microsoft.java.debug.core.adapter.AdapterUtils;
33+
import com.microsoft.java.debug.core.adapter.Constants;
34+
import com.microsoft.java.debug.core.adapter.IDebugAdapterContext;
35+
import com.microsoft.java.debug.core.adapter.ISourceLookUpProvider;
36+
2837
import org.eclipse.core.resources.IResource;
38+
import org.eclipse.core.runtime.CoreException;
2939
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
3040
import org.eclipse.jdt.core.IBuffer;
3141
import org.eclipse.jdt.core.IClassFile;
3242
import org.eclipse.jdt.core.IJavaElement;
43+
import org.eclipse.jdt.core.IJavaProject;
44+
import org.eclipse.jdt.core.IPackageFragmentRoot;
3345
import org.eclipse.jdt.core.ITypeRoot;
3446
import org.eclipse.jdt.core.JavaCore;
3547
import org.eclipse.jdt.core.JavaModelException;
3648
import org.eclipse.jdt.core.dom.AST;
3749
import org.eclipse.jdt.core.dom.ASTParser;
3850
import org.eclipse.jdt.core.dom.CompilationUnit;
51+
import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
3952
import org.eclipse.jdt.internal.debug.core.breakpoints.ValidBreakpointLocationLocator;
40-
41-
import com.microsoft.java.debug.core.Configuration;
42-
import com.microsoft.java.debug.core.DebugException;
43-
import com.microsoft.java.debug.core.adapter.AdapterUtils;
44-
import com.microsoft.java.debug.core.adapter.Constants;
45-
import com.microsoft.java.debug.core.adapter.IDebugAdapterContext;
46-
import com.microsoft.java.debug.core.adapter.ISourceLookUpProvider;
53+
import org.eclipse.jdt.launching.IVMInstall;
54+
import org.eclipse.jdt.launching.JavaRuntime;
55+
import org.eclipse.jdt.launching.LibraryLocation;
4756

4857
public class JdtSourceLookUpProvider implements ISourceLookUpProvider {
4958
private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME);
@@ -181,6 +190,25 @@ public String getSourceFileURI(String fullyQualifiedName, String sourcePath) {
181190
return null;
182191
}
183192

193+
@Override
194+
public String getJavaRuntimeVersion(String projectName) {
195+
IJavaProject project = JdtUtils.getJavaProject(projectName);
196+
if (project != null) {
197+
try {
198+
IVMInstall vmInstall = JavaRuntime.getVMInstall(project);
199+
if (vmInstall == null || vmInstall.getInstallLocation() == null) {
200+
return null;
201+
}
202+
203+
return resolveSystemLibraryVersion(project, vmInstall);
204+
} catch (CoreException e) {
205+
logger.log(Level.SEVERE, "Failed to get Java runtime version for project '" + projectName + "': " + e.getMessage(), e);
206+
}
207+
}
208+
209+
return null;
210+
}
211+
184212
/**
185213
* Get the project associated source containers.
186214
* @return the initialized source container list
@@ -280,4 +308,21 @@ private static String readFile(String filePath, Charset cs) {
280308
return builder.toString();
281309
}
282310

311+
private static String resolveSystemLibraryVersion(IJavaProject project, IVMInstall vmInstall) throws JavaModelException {
312+
LibraryLocation[] libraries = JavaRuntime.getLibraryLocations(vmInstall);
313+
if (libraries != null && libraries.length > 0) {
314+
IPackageFragmentRoot root = project.findPackageFragmentRoot(libraries[0].getSystemLibraryPath());
315+
if (!(root instanceof JarPackageFragmentRoot)) {
316+
return null;
317+
}
318+
Manifest manifest = ((JarPackageFragmentRoot) root).getManifest();
319+
if (manifest == null) {
320+
return null;
321+
}
322+
Attributes attributes = manifest.getMainAttributes();
323+
return attributes.getValue("Implementation-Version");
324+
}
325+
326+
return null;
327+
}
283328
}

com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/ResolveJavaExecutableHandler.java

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
package com.microsoft.java.debug.plugin.internal;
1313

1414
import java.io.File;
15-
import java.nio.file.Paths;
1615
import java.util.List;
1716
import java.util.Objects;
1817
import java.util.logging.Level;
@@ -61,28 +60,35 @@ public static String resolveJavaExecutable(List<Object> arguments) throws Except
6160
}
6261
}
6362

64-
if (targetProject == null) {
65-
return null;
66-
}
67-
68-
IVMInstall vmInstall = JavaRuntime.getVMInstall(targetProject);
69-
if (vmInstall == null || vmInstall.getInstallLocation() == null) {
70-
return null;
71-
}
72-
73-
File exe = findJavaExecutable(vmInstall.getInstallLocation());
74-
if (exe == null) {
75-
return null;
76-
}
77-
78-
return exe.getAbsolutePath();
63+
return resolveJavaExecutable(targetProject);
7964
} catch (CoreException e) {
8065
logger.log(Level.SEVERE, "Failed to resolve java executable: " + e.getMessage(), e);
8166
}
8267

8368
return null;
8469
}
8570

71+
/**
72+
* Resolve the Java executable path from the project's Java runtime.
73+
*/
74+
public static String resolveJavaExecutable(IJavaProject javaProject) throws CoreException {
75+
if (javaProject == null) {
76+
return null;
77+
}
78+
79+
IVMInstall vmInstall = JavaRuntime.getVMInstall(javaProject);
80+
if (vmInstall == null || vmInstall.getInstallLocation() == null) {
81+
return null;
82+
}
83+
84+
File exe = findJavaExecutable(vmInstall.getInstallLocation());
85+
if (exe == null) {
86+
return null;
87+
}
88+
89+
return exe.getAbsolutePath();
90+
}
91+
8692
private static File findJavaExecutable(File vmInstallLocation) {
8793
boolean isBin = Objects.equals("bin", vmInstallLocation.getName());
8894
for (int i = 0; i < javaExecCandidates.length; i++) {
@@ -91,8 +97,7 @@ private static File findJavaExecutable(File vmInstallLocation) {
9197
continue;
9298
}
9399

94-
String execRelativePath = j == 0 ? javaExecCandidates[i] : Paths.get(javaBinCandidates[j], javaExecCandidates[i]).toString();
95-
File javaFile = new File(vmInstallLocation, execRelativePath);
100+
File javaFile = new File(vmInstallLocation, javaBinCandidates[j] + javaExecCandidates[i]);
96101
if (javaFile.isFile()) {
97102
return javaFile;
98103
}

0 commit comments

Comments
 (0)