41 * |
41 * |
42 * This class only depends on the JDK so that it can be used without building Graal. |
42 * This class only depends on the JDK so that it can be used without building Graal. |
43 */ |
43 */ |
44 public final class JVMCIVersionCheck { |
44 public final class JVMCIVersionCheck { |
45 |
45 |
46 private static final Version JVMCI8_MIN_VERSION = new Version3(19, 3, 2); |
46 private static final Version JVMCI_MIN_VERSION = new Version3(19, 3, 4); |
47 |
47 |
48 public interface Version { |
48 public interface Version { |
49 boolean isLessThan(Version other); |
49 boolean isLessThan(Version other); |
50 |
50 |
51 static Version parse(String vmVersion) { |
51 static Version parse(String vmVersion) { |
143 public String toString() { |
143 public String toString() { |
144 return String.format("%d.%d-b%02d", major, minor, build); |
144 return String.format("%d.%d-b%02d", major, minor, build); |
145 } |
145 } |
146 } |
146 } |
147 |
147 |
148 private static void failVersionCheck(Map<String, String> props, boolean exit, String reason, Object... args) { |
148 private void failVersionCheck(boolean exit, String reason, Object... args) { |
149 Formatter errorMessage = new Formatter().format(reason, args); |
149 Formatter errorMessage = new Formatter().format(reason, args); |
150 String javaHome = props.get("java.home"); |
150 String javaHome = props.get("java.home"); |
151 String vmName = props.get("java.vm.name"); |
151 String vmName = props.get("java.vm.name"); |
152 errorMessage.format("Set the JVMCI_VERSION_CHECK environment variable to \"ignore\" to suppress "); |
152 errorMessage.format("Set the JVMCI_VERSION_CHECK environment variable to \"ignore\" to suppress "); |
153 errorMessage.format("this error or to \"warn\" to emit a warning and continue execution.%n"); |
153 errorMessage.format("this error or to \"warn\" to emit a warning and continue execution.%n"); |
154 errorMessage.format("Currently used Java home directory is %s.%n", javaHome); |
154 errorMessage.format("Currently used Java home directory is %s.%n", javaHome); |
155 errorMessage.format("Currently used VM configuration is: %s%n", vmName); |
155 errorMessage.format("Currently used VM configuration is: %s%n", vmName); |
156 if (props.get("java.specification.version").compareTo("1.9") < 0) { |
156 if (javaSpecVersion.compareTo("1.9") < 0) { |
157 errorMessage.format("Download the latest JVMCI JDK 8 from https://github.com/graalvm/openjdk8-jvmci-builder/releases"); |
157 errorMessage.format("Download the latest JVMCI JDK 8 from https://github.com/graalvm/openjdk8-jvmci-builder/releases"); |
158 } else { |
158 } else { |
159 errorMessage.format("Download JDK 11 or later."); |
159 if (javaSpecVersion.compareTo("11") == 0 && vmVersion.contains("-jvmci-")) { |
|
160 errorMessage.format("Download the latest Labs OpenJDK 11 from https://github.com/graalvm/labs-openjdk-11/releases"); |
|
161 } else { |
|
162 errorMessage.format("Download JDK 11 or later."); |
|
163 } |
160 } |
164 } |
161 String value = System.getenv("JVMCI_VERSION_CHECK"); |
165 String value = System.getenv("JVMCI_VERSION_CHECK"); |
162 if ("warn".equals(value)) { |
166 if ("warn".equals(value)) { |
163 System.err.println(errorMessage.toString()); |
167 System.err.println(errorMessage.toString()); |
164 } else if ("ignore".equals(value)) { |
168 } else if ("ignore".equals(value)) { |
181 this.vmVersion = vmVersion; |
185 this.vmVersion = vmVersion; |
182 } |
186 } |
183 |
187 |
184 static void check(Map<String, String> props, boolean exitOnFailure) { |
188 static void check(Map<String, String> props, boolean exitOnFailure) { |
185 JVMCIVersionCheck checker = new JVMCIVersionCheck(props, props.get("java.specification.version"), props.get("java.vm.version")); |
189 JVMCIVersionCheck checker = new JVMCIVersionCheck(props, props.get("java.specification.version"), props.get("java.vm.version")); |
186 checker.run(exitOnFailure, JVMCI8_MIN_VERSION); |
190 checker.run(exitOnFailure, JVMCI_MIN_VERSION); |
187 } |
191 } |
188 |
192 |
189 /** |
193 /** |
190 * Entry point for testing. |
194 * Entry point for testing. |
191 */ |
195 */ |
200 private void run(boolean exitOnFailure, Version minVersion) { |
204 private void run(boolean exitOnFailure, Version minVersion) { |
201 if (javaSpecVersion.compareTo("1.9") < 0) { |
205 if (javaSpecVersion.compareTo("1.9") < 0) { |
202 Version v = Version.parse(vmVersion); |
206 Version v = Version.parse(vmVersion); |
203 if (v != null) { |
207 if (v != null) { |
204 if (v.isLessThan(minVersion)) { |
208 if (v.isLessThan(minVersion)) { |
205 failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion); |
209 failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion); |
206 } |
210 } |
207 return; |
211 return; |
208 } |
212 } |
209 failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + |
213 failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + |
210 "Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion); |
214 "Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion); |
211 } else if (javaSpecVersion.compareTo("11") < 0) { |
215 } else if (javaSpecVersion.compareTo("11") < 0) { |
212 failVersionCheck(props, exitOnFailure, "Graal is not compatible with the JVMCI API in JDK 9 and 10.%n"); |
216 failVersionCheck(exitOnFailure, "Graal is not compatible with the JVMCI API in JDK 9 and 10.%n"); |
213 } else { |
217 } else { |
214 if (vmVersion.contains("SNAPSHOT")) { |
218 if (vmVersion.contains("SNAPSHOT")) { |
215 return; |
219 return; |
216 } |
220 } |
217 if (vmVersion.contains("internal")) { |
221 if (vmVersion.contains("internal")) { |
218 // Allow local builds |
222 // Allow local builds |
219 return; |
223 return; |
220 } |
224 } |
221 if (vmVersion.startsWith("11-ea+")) { |
225 if (vmVersion.contains("-jvmci-")) { |
222 String buildString = vmVersion.substring("11-ea+".length()); |
|
223 try { |
|
224 int build = Integer.parseInt(buildString); |
|
225 if (build < 20) { |
|
226 failVersionCheck(props, exitOnFailure, "Graal requires build 20 or later of JDK 11 early access binary, got build %d.%n", build); |
|
227 return; |
|
228 } |
|
229 } catch (NumberFormatException e) { |
|
230 failVersionCheck(props, exitOnFailure, "Could not parse the JDK 11 early access build number from java.vm.version property: %s.%n", vmVersion); |
|
231 return; |
|
232 } |
|
233 } else if (vmVersion.contains("-jvmci-")) { |
|
234 // A "labsjdk" |
226 // A "labsjdk" |
235 Version v = Version.parse(vmVersion); |
227 Version v = Version.parse(vmVersion); |
236 if (v != null) { |
228 if (v != null) { |
237 if (v.isLessThan(minVersion)) { |
229 if (v.isLessThan(minVersion)) { |
238 failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion); |
230 failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion); |
239 } |
231 } |
240 return; |
232 return; |
241 } |
233 } |
242 failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + |
234 failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + |
243 "Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion); |
235 "Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion); |
244 } else { |
236 } else { |
245 // Graal is compatible with all JDK versions as of 11 GA. |
237 // Graal is compatible with all JDK versions as of 11 GA. |
246 } |
238 } |
247 } |
239 } |