Skip to content

Commit 4efdb8a

Browse files
authored
Select the best matching JRE for an EE from the list of compatible JVMs (#761)
Currently the selection of a compatible JRE for an EE seems quite random for the user, e.g. it can happen that for an EE10 with some JRE11/17/24 it chooses 24. This is actually a bad choice as newer java might _remove_ API during release, so the _lowest_ possible java version among others would be the best choice here. This now do the following: - introduce a new method IExecutionEnvironment#getCompatibleVM that selects the best matching from the set of selected JVMs (but ignoring the default) - in the JREContainerInitializer check if there is a default vm selected, then use that - if not ask the EE for a compatible one (with the new method)
1 parent 2dcafc0 commit 4efdb8a

File tree

5 files changed

+93
-26
lines changed

5 files changed

+93
-26
lines changed

org.eclipse.jdt.launching/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %pluginName
44
Bundle-SymbolicName: org.eclipse.jdt.launching; singleton:=true
5-
Bundle-Version: 3.23.500.qualifier
5+
Bundle-Version: 3.24.0.qualifier
66
Bundle-Activator: org.eclipse.jdt.internal.launching.LaunchingPlugin
77
Bundle-Vendor: %providerName
88
Bundle-Localization: plugin

org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JREContainerInitializer.java

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.io.File;
2020
import java.net.MalformedURLException;
2121
import java.net.URL;
22-
import java.util.Arrays;
2322

2423
import org.eclipse.core.runtime.CoreException;
2524
import org.eclipse.core.runtime.IPath;
@@ -178,31 +177,16 @@ public static IVMInstall resolveVM(IExecutionEnvironment environment) {
178177
}
179178
IVMInstall vm = environment.getDefaultVM();
180179
if (vm == null) {
181-
IVMInstall[] installs = environment.getCompatibleVMs();
182-
// take the first strictly compatible VM if there is no default
183-
if (installs.length == 0 && LaunchingPlugin.DEBUG_JRE_CONTAINER) {
180+
vm = environment.getCompatibleVM();
181+
if (vm == null) {
184182
LaunchingPlugin.trace("\t*** NO COMPATIBLE VMS ***"); //$NON-NLS-1$
183+
return null;
185184
}
186-
for (int i = 0; i < installs.length; i++) {
187-
IVMInstall install = installs[i];
188-
if (environment.isStrictlyCompatible(install)) {
189-
vm = install;
190-
if (LaunchingPlugin.DEBUG_JRE_CONTAINER) {
191-
LaunchingPlugin.trace("\tPerfect Match: " + vm.getName()); //$NON-NLS-1$
192-
}
193-
break;
194-
}
195-
}
196-
//try the default VM install: https://bugs.eclipse.org/bugs/show_bug.cgi?id=371300
197-
// if default vm is a match https://bugs.eclipse.org/bugs/show_bug.cgi?id=484026
198-
if (vm == null && installs.length > 0 && Arrays.asList(installs).contains(JavaRuntime.getDefaultVMInstall())) {
199-
vm = JavaRuntime.getDefaultVMInstall();
200-
}
201-
// use the first VM failing that
202-
if (vm == null && installs.length > 0) {
203-
vm = installs[0];
204-
if (LaunchingPlugin.DEBUG_JRE_CONTAINER) {
205-
LaunchingPlugin.trace("\tFirst Match: " + vm.getName()); //$NON-NLS-1$
185+
if (LaunchingPlugin.DEBUG_JRE_CONTAINER) {
186+
if (environment.isStrictlyCompatible(vm)) {
187+
LaunchingPlugin.trace("\tPerfect Match: " + vm.getName()); //$NON-NLS-1$
188+
} else {
189+
LaunchingPlugin.trace("\tUse compatible VM: " + vm.getName()); //$NON-NLS-1$
206190
}
207191
}
208192
} else {

org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/ExecutionEnvironment.java

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.eclipse.jdt.core.JavaModelException;
4343
import org.eclipse.jdt.internal.launching.LaunchingPlugin;
4444
import org.eclipse.jdt.launching.IVMInstall;
45+
import org.eclipse.jdt.launching.IVMInstall2;
4546
import org.eclipse.jdt.launching.IVMInstallChangedListener;
4647
import org.eclipse.jdt.launching.JavaRuntime;
4748
import org.eclipse.jdt.launching.LibraryLocation;
@@ -210,6 +211,75 @@ public IVMInstall[] getCompatibleVMs() {
210211
return fCompatibleVMs.toArray(new IVMInstall[fCompatibleVMs.size()]);
211212
}
212213

214+
@Override
215+
public IVMInstall getCompatibleVM() {
216+
init();
217+
if (fCompatibleVMs.isEmpty()) {
218+
return null;
219+
}
220+
if (fCompatibleVMs.size() == 1) {
221+
return fCompatibleVMs.get(0);
222+
}
223+
if (!fStrictlyCompatible.isEmpty()) {
224+
// first lean to the default if it is strictly compatible
225+
IVMInstall workspaceDefaultVMInstall = JavaRuntime.getDefaultVMInstall();
226+
if (fStrictlyCompatible.contains(workspaceDefaultVMInstall)) {
227+
return workspaceDefaultVMInstall;
228+
}
229+
return fStrictlyCompatible.iterator().next();
230+
}
231+
IVMInstall best = null;
232+
java.lang.Runtime.Version bestVersion = null;
233+
for (IVMInstall vm : fCompatibleVMs) {
234+
java.lang.Runtime.Version vmVersion = getRuntimeVersion(vm);
235+
if (isBetter(vmVersion, bestVersion)) {
236+
bestVersion = vmVersion;
237+
best = vm;
238+
}
239+
}
240+
return best;
241+
}
242+
243+
private boolean isBetter(java.lang.Runtime.Version version, java.lang.Runtime.Version other) {
244+
if (other == null) {
245+
return true;
246+
}
247+
if (version == null) {
248+
return false;
249+
}
250+
if (version.feature() < other.feature()) {
251+
// lower major (== feature) is better!
252+
return true;
253+
}
254+
if (version.feature() > other.feature()) {
255+
// higher is not better!
256+
return false;
257+
}
258+
if (version.feature() == 1) {
259+
// special case for java 1.x versions, lower minor (== interim) is better!
260+
if (version.interim() < other.interim()) {
261+
return true;
262+
}
263+
if (version.interim() > other.interim()) {
264+
return false;
265+
}
266+
}
267+
// when we are here we have equally good versions, e.g. two Java 11, we choose now the one that is better in the given interim/patch levels
268+
// and can use the default compare of version
269+
return version.compareTo(other) > 0;
270+
}
271+
272+
private java.lang.Runtime.Version getRuntimeVersion(IVMInstall vm) {
273+
if (vm instanceof IVMInstall2 vm2) {
274+
try {
275+
return Runtime.Version.parse(vm2.getJavaVersion());
276+
} catch (RuntimeException e) {
277+
// in this case we can't know the version...
278+
}
279+
}
280+
return null;
281+
}
282+
213283
/* (non-Javadoc)
214284
* @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#isStrictlyCompatible(org.eclipse.jdt.launching.IVMInstall)
215285
*/

org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/environments/IExecutionEnvironment.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,19 @@ public interface IExecutionEnvironment {
6464
*/
6565
public IVMInstall[] getCompatibleVMs();
6666

67+
/**
68+
* Return the vm that is best matching this environment that is:
69+
*
70+
* <ol>
71+
* <li>if a strictly compatible is found this one is returned, if multiple are strictly compatible it picks one randomly</li>
72+
* <li>in all other case it choose the one with the lowest version, if multiple match the same version it picks one randomly</li>
73+
* </ol>
74+
*
75+
* @return the best compatible VM or <code>null</code> if none is found
76+
* @since 3.24
77+
*/
78+
public IVMInstall getCompatibleVM();
79+
6780
/**
6881
* Returns whether the specified VM install is strictly compatible with
6982
* this environment. Returns <code>true</code> to indicate the VM install

org.eclipse.jdt.launching/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
</parent>
1919
<groupId>org.eclipse.jdt</groupId>
2020
<artifactId>org.eclipse.jdt.launching</artifactId>
21-
<version>3.23.500-SNAPSHOT</version>
21+
<version>3.24.0-SNAPSHOT</version>
2222
<packaging>eclipse-plugin</packaging>
2323

2424
<build>

0 commit comments

Comments
 (0)