Skip to content

[GR-65661] Polyglot version check in HotSpotTruffleRuntimeAccess still accepts JDK-21. #11967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ private static MethodHandle findVersionGetComponent() {
}

private static final String NATIVE_IMAGE_FILELIST_FILE_NAME = "native-image-resources.filelist";
/**
* When modifying the version values defined below, ensure that the corresponding version fields
* in {@code TruffleVersions} are also updated accordingly to maintain consistency.
*/
private static final Version NEXT_POLYGLOT_VERSION_UPDATE = Version.create(29, 1);
private static final int MAX_JDK_VERSION = 29;

Expand All @@ -192,7 +196,7 @@ public String getURL() {

@Override
public String getDescription() {
return "Provides support for Truffle languages";
return "Provides internal support for Truffle";
}

public static Class<?> lookupClass(String className) {
Expand Down Expand Up @@ -327,7 +331,11 @@ private void processInlinedField(DuringAnalysisAccess access, InlinableField inl

@Override
public void afterRegistration(AfterRegistrationAccess a) {
if (!Boolean.getBoolean("polyglotimpl.DisableVersionChecks")) {
/*
* The actual check is now performed in the Truffle API (TruffleAPIFeature). This fallback
* branch can be removed once all supported Truffle versions include TruffleAPIFeature.
*/
if (!Boolean.getBoolean("polyglotimpl.DisableVersionChecks") && !hasTruffleAPIFeature(a)) {
Version truffleVersion = getTruffleVersion(a);
Version truffleMajorMinorVersion = stripUpdateVersion(truffleVersion);
Version featureVersion = getSVMFeatureVersion();
Expand Down Expand Up @@ -377,6 +385,11 @@ public void afterRegistration(AfterRegistrationAccess a) {
profilingEnabled = false;
}

private static boolean hasTruffleAPIFeature(AfterRegistrationAccess a) {
Class<?> featureClass = a.findClassByName("com.oracle.truffle.api.impl.TruffleAPIFeature");
return featureClass != null && ((FeatureImpl.AfterRegistrationAccessImpl) a).getFeatureHandler().containsFeature(featureClass);
}

/**
* Reads reflectively the org.graalvm.truffle module version. The method uses reflection to
* access the {@code PolyglotImpl#TRUFFLE_VERSION} field because the Truffle API may be of a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public String getURL() {

@Override
public String getDescription() {
return "Provides support for Truffle runtime compilation";
return "Provides internal support for Truffle runtime compilation";
}

public static class Options {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ ForceOnModulePath = org.graalvm.truffle
Args = --macro:truffle-svm \
--features=com.oracle.svm.truffle.TruffleBaseFeature \
--features=com.oracle.truffle.api.object.DynamicObjectFeature \
--features=com.oracle.truffle.api.impl.TruffleAPIFeature \
--initialize-at-build-time=com.oracle.truffle \
--initialize-at-build-time=org.graalvm.jniutils \
--initialize-at-build-time=org.graalvm.nativebridge \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or
* data (collectively the "Software"), free of charge and under any and all
* copyright rights in the Software, and any and all patent rights owned or
* freely licensable by each licensor hereunder covering either (i) the
* unmodified Software as contributed to or provided by such licensor, or (ii)
* the Larger Works (as defined below), to deal in both
*
* (a) the Software, and
*
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
*
* The above copyright notice and either this complete permission notice or at a
* minimum a reference to the UPL must be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.oracle.truffle.api.impl;

import com.oracle.truffle.api.CompilerDirectives;
import org.graalvm.home.Version;
import org.graalvm.nativeimage.hosted.Feature;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;

public final class TruffleAPIFeature implements Feature {

@Override
public String getURL() {
return "https://github.com/oracle/graal/tree/master/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/TruffleAPIFeature.java";
}

@Override
public String getDescription() {
return "Provides basic support for Truffle";
}

@Override
public void afterRegistration(AfterRegistrationAccess access) {
String result = doVersionCheck();
if (result != null) {
// GR-67329: Exceptions thrown by features do not include their error messages in the
// native-image output
PrintStream out = System.err;
out.printf("[%s] %s", getClass().getName(), result);
throw new IllegalStateException(result);
}
}

private static String doVersionCheck() {
if (TruffleVersions.isVersionCheckEnabled()) {
Version truffleAPIVersion = TruffleVersions.TRUFFLE_API_VERSION;
Version truffleMajorMinorVersion = stripUpdateVersion(truffleAPIVersion);
Version truffleSVMVersion = getSVMFeatureVersion();
Version truffleSVMMajorMinorVersion = stripUpdateVersion(truffleSVMVersion);
if (truffleSVMVersion.compareTo(TruffleVersions.NEXT_VERSION_UPDATE) >= 0) {
throw new AssertionError("MIN_COMPILER_VERSION, MIN_JDK_VERSION and MAX_JDK_VERSION must be updated!");
} else if (truffleSVMMajorMinorVersion.compareTo(truffleMajorMinorVersion) > 0) {
// no forward compatibility
return formatVersionWarningMessage("""
Your Java runtime '%s' with native-image feature version '%s' is incompatible with polyglot version '%s'.
Update the org.graalvm.polyglot versions to at least '%s' to resolve this.
""", Runtime.version(), truffleSVMVersion, truffleAPIVersion, truffleSVMVersion);
} else if (Runtime.version().feature() < TruffleVersions.MIN_JDK_VERSION) {
return formatVersionWarningMessage("""
Your Java runtime '%s' with native-image feature version '%s' is incompatible with polyglot version '%s'.
The Java runtime version must be greater or equal to JDK '%d'.
Update your Java runtime to resolve this.
""", Runtime.version(), truffleSVMVersion, truffleAPIVersion, TruffleVersions.MIN_JDK_VERSION);
} else if (truffleSVMVersion.compareTo(TruffleVersions.MIN_COMPILER_VERSION) < 0) {
return formatVersionWarningMessage("""
Your Java runtime '%s' with compiler version '%s' is incompatible with polyglot version '%s'.
Update the Java runtime to the latest update release of JDK '%d'.
""", Runtime.version(), truffleSVMVersion, truffleAPIVersion, Runtime.version().feature());
}
}
return null;
}

/**
* Reads the version of the Truffle feature.
*/
private static Version getSVMFeatureVersion() {
InputStream in = TruffleAPIFeature.class.getClassLoader().getResourceAsStream("META-INF/graalvm/org.graalvm.truffle.runtime.svm/version");
if (in == null) {
throw CompilerDirectives.shouldNotReachHere("Truffle native image feature must have a version file.");
}
try (BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
return Version.parse(r.readLine());
} catch (IOException ioe) {
throw CompilerDirectives.shouldNotReachHere(ioe);
}
}

private static Version stripUpdateVersion(Version version) {
int major = version.getComponent(0);
int minor = version.getComponent(1);
if (major == 0 && minor == 0) {
/*
* Version represents a pure snapshot version without any numeric component.
*/
return version;
} else {
return Version.create(major, minor);
}
}

private static String formatVersionWarningMessage(String errorFormat, Object... args) {
StringBuilder errorMessage = new StringBuilder("Version check failed.\n");
errorMessage.append(String.format(errorFormat, args));
errorMessage.append("""
To disable this version check the '-Dpolyglotimpl.DisableVersionChecks=true' system property can be used.
It is not recommended to disable version checks.
""");
return errorMessage.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or
* data (collectively the "Software"), free of charge and under any and all
* copyright rights in the Software, and any and all patent rights owned or
* freely licensable by each licensor hereunder covering either (i) the
* unmodified Software as contributed to or provided by such licensor, or (ii)
* the Larger Works (as defined below), to deal in both
*
* (a) the Software, and
*
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
*
* The above copyright notice and either this complete permission notice or at a
* minimum a reference to the UPL must be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.oracle.truffle.api.impl;

import org.graalvm.home.Version;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

/**
* Provides support for verifying compatibility between the Truffle API, Truffle compiler, and
* Truffle SubstrateVM feature versions.
*/
public final class TruffleVersions {

public static final int MIN_JDK_VERSION = 21;
public static final int MAX_JDK_VERSION = 29;
public static final Version MIN_COMPILER_VERSION = Version.create(23, 1, 2);
public static final Version NEXT_VERSION_UPDATE = Version.create(29, 1);
public static final Version TRUFFLE_API_VERSION;
static {
if (isVersionCheckEnabled()) {
InputStream in = TruffleVersions.class.getResourceAsStream("/META-INF/graalvm/org.graalvm.truffle/version");
if (in == null) {
throw new InternalError("Truffle API must have a version file.");
}
try (BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
TRUFFLE_API_VERSION = Version.parse(r.readLine());
} catch (IOException ioe) {
throw new InternalError(ioe);
}
} else {
TRUFFLE_API_VERSION = null;
}
}

private TruffleVersions() {
}

/**
* Determines whether version checks are currently enabled.
*/
public static boolean isVersionCheckEnabled() {
return !Boolean.getBoolean("polyglotimpl.DisableVersionChecks");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,9 @@
import static com.oracle.truffle.polyglot.EngineAccessor.INSTRUMENT;
import static com.oracle.truffle.polyglot.EngineAccessor.LANGUAGE;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.lang.ref.Reference;
Expand All @@ -58,7 +56,6 @@
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
Expand All @@ -74,6 +71,7 @@
import java.util.logging.Level;
import java.util.stream.Collectors;

import com.oracle.truffle.api.impl.TruffleVersions;
import org.graalvm.options.OptionDescriptors;
import org.graalvm.polyglot.Engine;
import org.graalvm.polyglot.HostAccess.TargetMappingPrecedence;
Expand Down Expand Up @@ -127,22 +125,10 @@ public final class PolyglotImpl extends AbstractPolyglotImpl {
static final Object SECRET = new Object();
static final Object[] EMPTY_ARGS = new Object[0];

static final String TRUFFLE_VERSION;
static {
if (Boolean.getBoolean("polyglotimpl.DisableVersionChecks")) {
TRUFFLE_VERSION = null;
} else {
InputStream in = PolyglotImpl.class.getResourceAsStream("/META-INF/graalvm/org.graalvm.truffle/version");
if (in == null) {
throw new InternalError("Truffle API must have a version file.");
}
try (BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
TRUFFLE_VERSION = r.readLine();
} catch (IOException ioe) {
throw new InternalError(ioe);
}
}
}
/*
* Accessed reflectively by TruffleBaseFeature.
*/
static final String TRUFFLE_VERSION = TruffleVersions.TRUFFLE_API_VERSION == null ? null : TruffleVersions.TRUFFLE_API_VERSION.toString();

private final PolyglotSourceDispatch sourceDispatch = new PolyglotSourceDispatch(this);
private final PolyglotSourceSectionDispatch sourceSectionDispatch = new PolyglotSourceSectionDispatch(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@

import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.UnmodifiableEconomicMap;
import org.graalvm.home.Version;
import org.graalvm.nativeimage.ImageInfo;
import org.graalvm.options.OptionCategory;
import org.graalvm.options.OptionDescriptor;
Expand Down Expand Up @@ -168,10 +167,6 @@
public abstract class OptimizedTruffleRuntime implements TruffleRuntime, TruffleCompilerRuntime {

private static final int JAVA_SPECIFICATION_VERSION = Runtime.version().feature();
public static final Version MIN_COMPILER_VERSION = Version.create(23, 1, 2);
public static final int MIN_JDK_VERSION = 21;
public static final int MAX_JDK_VERSION = 29;
public static final Version NEXT_VERSION_UPDATE = Version.create(29, 1);

/**
* Used only to reset state for native image compilation.
Expand Down
Loading
Loading