Skip to content

Commit bea9acc

Browse files
committed
Check major version of running JVM matches agent; warn if full version differs.
1 parent 104d440 commit bea9acc

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

substratevm/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ This changelog summarizes major changes to GraalVM Native Image.
44

55
## GraalVM for JDK 25
66
* (GR-58668) Enabled [Whole-Program Sparse Conditional Constant Propagation (WP-SCCP)](https://github.com/oracle/graal/pull/9821) by default, improving the precision of points-to analysis in Native Image. This optimization enhances static analysis accuracy and scalability, potentially reducing the size of the final native binary.
7+
* (GR-59864) Added JVM version check to the Native Image agent. The agent will abort execution if the JVM major version does not match the version it was built with, and warn if the full JVM version is different.
78

89
## GraalVM for JDK 24 (Internal Version 24.2.0)
910
* (GR-59717) Added `DuringSetupAccess.registerObjectReachabilityHandler` to allow registering a callback that is executed when an object of a specified type is marked as reachable during heap scanning.

substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgent.java

+31
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
224224
}
225225
}
226226

227+
if (!checkJVMVersion(jvmti)) {
228+
return USAGE_ERROR;
229+
}
230+
227231
if (traceOutputFile == null && configOutputDir == null) {
228232
configOutputDir = transformPath(AGENT_NAME + "_config-pid{pid}-{datetime}/");
229233
inform("no output options provided, tracking dynamic accesses and writing configuration to directory: " + configOutputDir);
@@ -420,6 +424,33 @@ private static int usage(String message) {
420424
return USAGE_ERROR;
421425
}
422426

427+
private static boolean checkJVMVersion(JvmtiEnv jvmti) {
428+
String agentVersion = System.getProperty("java.vm.version");
429+
int agentMajorVersion = Runtime.version().feature();
430+
431+
String vmVersion = Support.getSystemProperty(jvmti, "java.vm.version");
432+
if (vmVersion == null) {
433+
warn(String.format("Unable to determine the \"java.vm.version\" of the running JVM. Note that the JVM should have major version %d, otherwise metadata may be incorrect.",
434+
agentMajorVersion));
435+
return true;
436+
}
437+
438+
// Fail if the major versions differ.
439+
if (!vmVersion.startsWith(Integer.toString(agentMajorVersion))) {
440+
return error(false, String.format(
441+
"The current VM (%s) is incompatible with the agent, which was built for a JVM with major version %d. To resolve this issue, run the agent using a JVM with major version %d.",
442+
vmVersion, agentMajorVersion, agentMajorVersion));
443+
}
444+
445+
// Warn if the VM is different.
446+
if (!vmVersion.startsWith(agentVersion)) {
447+
warn(String.format(
448+
"The running JVM (%s) is different from the JVM used to build the agent (%s). If the generated metadata is incorrect or incomplete, consider running the agent using the same JVM that built it.",
449+
vmVersion, agentVersion));
450+
}
451+
return true;
452+
}
453+
423454
private static AccessAdvisor createAccessAdvisor(boolean builtinHeuristicFilter, ConfigurationFilter callerFilter, ConfigurationFilter accessFilter) {
424455
AccessAdvisor advisor = new AccessAdvisor();
425456
advisor.setHeuristicsEnabled(builtinHeuristicFilter);

0 commit comments

Comments
 (0)