Skip to content

Commit d90ad08

Browse files
committed
[GR-66339] Check if Multi-Release classes are correctly loaded and error otherwise
PullRequest: graal/21210
2 parents 6c324eb + 6075315 commit d90ad08

File tree

6 files changed

+259
-1
lines changed

6 files changed

+259
-1
lines changed

docs/reference-manual/embedding/embed-languages.md

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ In this example, `lib/polyglot` directory should contain all polyglot and langua
9393
To access polyglot classes from the class path, you must also specify the `--add-modules=org.graalvm.polyglot` JVM option.
9494
If you are using [GraalVM Native Image](#build-native-executables-from-polyglot-applications), polyglot modules on the class path will be automatically upgraded to the module path.
9595

96-
While we do support creating single uber JAR files from polyglot libraries, for example, using the Maven Assembly plugin, but we do not recommend it.
96+
While we do support [creating single uber JAR files](#uber-jar-file-creation) from polyglot libraries, for example, using the Maven Assembly plugin, we do not recommend it.
9797
Also note that uber JAR files are not supported when creating native binaries with GraalVM Native Image.
9898

9999
## Compile and Run a Polyglot Application
@@ -941,6 +941,131 @@ In this code:
941941
- The `context.eval()` call evaluates a specified snippet of guest language code.
942942
- The `listener.close()` closes a listener earlier, however execution listeners are automatically closed with the engine.
943943
944+
## Uber JAR File Creation
945+
946+
Uber JARs are JAR files that bundle all dependencies into a single archive for easier distribution.
947+
However, creating an Uber JAR is not recommended for Graal languages because it breaks module descriptors, file integrity metadata, and JAR signature information.
948+
Uber JARs are only supported on HotSpot and are not supported for native image generation, as the Native Image tool requires intact Java module descriptors.
949+
950+
If you must use Uber JARs, use the minimal configuration below and verify that it is still up to date whenever you upgrade.
951+
952+
You can find a working example of valid Maven Shade and Assembly plugin configurations in the [polyglot embedding example](https://github.com/graalvm/polyglot-embedding-demo?tab=readme-ov-file#maven-usage).
953+
See the `shade` and `assembly` profiles in [_pom.xml_](https://github.com/graalvm/polyglot-embedding-demo/blob/main/pom.xml#L384).
954+
955+
### Maven Shade Plugin
956+
957+
If you intend to use the Maven Shade plugin, include at least the following transformers and filter configuration:
958+
959+
```xml
960+
<profile>
961+
<id>shade</id>
962+
<build>
963+
<plugins>
964+
<plugin>
965+
<groupId>org.apache.maven.plugins</groupId>
966+
<artifactId>maven-shade-plugin</artifactId>
967+
<version>3.5.1</version>
968+
<executions>
969+
<execution>
970+
<phase>package</phase>
971+
<goals>
972+
<goal>shade</goal>
973+
</goals>
974+
</execution>
975+
</executions>
976+
<configuration>
977+
<transformers>
978+
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
979+
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
980+
<mainClass>org.example.embedding.Main</mainClass>
981+
<manifestEntries>
982+
<Multi-Release>true</Multi-Release>
983+
</manifestEntries>
984+
</transformer>
985+
</transformers>
986+
<filters>
987+
<!-- Filters JAR signature files -->
988+
<filter>
989+
<artifact>*:*:*:*</artifact>
990+
<excludes>
991+
<exclude>META-INF/*.SF</exclude>
992+
<exclude>META-INF/*.DSA</exclude>
993+
<exclude>META-INF/*.RSA</exclude>
994+
</excludes>
995+
</filter>
996+
</filters>
997+
</configuration>
998+
</plugin>
999+
</plugins>
1000+
</build>
1001+
</profile>
1002+
```
1003+
1004+
### Maven Assembly plugin
1005+
1006+
If you are using the Maven Assembly plugin, you may apply the following configuration:
1007+
1008+
```xml
1009+
<profile>
1010+
<id>assembly</id>
1011+
<build>
1012+
<plugins>
1013+
<plugin>
1014+
<groupId>org.apache.maven.plugins</groupId>
1015+
<artifactId>maven-assembly-plugin</artifactId>
1016+
<version>3.6.0</version>
1017+
<executions>
1018+
<execution>
1019+
<phase>package</phase>
1020+
<goals>
1021+
<goal>single</goal>
1022+
</goals>
1023+
<configuration>
1024+
<archive>
1025+
<manifest>
1026+
<mainClass>org.example.embedding.Main</mainClass>
1027+
</manifest>
1028+
<manifestEntries>
1029+
<Multi-Release>true</Multi-Release>
1030+
</manifestEntries>
1031+
</archive>
1032+
<descriptors>
1033+
<descriptor>assembly.xml</descriptor>
1034+
</descriptors>
1035+
</configuration>
1036+
</execution>
1037+
</executions>
1038+
</plugin>
1039+
</plugins>
1040+
</build>
1041+
</profile>
1042+
```
1043+
with the corresponding `assembly.xml`:
1044+
1045+
```xml
1046+
<?xml version="1.0" encoding="UTF-8"?>
1047+
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd">
1048+
<id>jar-with-dependencies</id>
1049+
<formats>
1050+
<format>jar</format>
1051+
</formats>
1052+
<includeBaseDirectory>false</includeBaseDirectory>
1053+
<dependencySets>
1054+
<dependencySet>
1055+
<outputDirectory>/</outputDirectory>
1056+
<useProjectArtifact>true</useProjectArtifact>
1057+
<unpack>true</unpack>
1058+
<scope>runtime</scope>
1059+
</dependencySet>
1060+
</dependencySets>
1061+
<containerDescriptorHandlers>
1062+
<containerDescriptorHandler>
1063+
<handlerName>metaInf-services</handlerName>
1064+
</containerDescriptorHandler>
1065+
</containerDescriptorHandlers>
1066+
</assembly
1067+
```
1068+
9441069
## Compatibility with JSR-223 ScriptEngine
9451070
9461071
<!--

sdk/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This changelog summarizes major changes between GraalVM SDK versions. The main f
1414
* GR-64488 FileSystem implementations can now provide disk-related metadata, including [total space](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/io/FileSystem.html##getFileStoreTotalSpace(java.nio.file.Path)), [usable space](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/io/FileSystem.html#getFileStoreUsableSpace(java.nio.file.Path)), [unallocated space](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/io/FileSystem.html#getFileStoreUnallocatedSpace(java.nio.file.Path)), [block size](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/io/FileSystem.html#getFileStoreBlockSize(java.nio.file.Path)), and [read-only status](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/io/FileSystem.html#isFileStoreReadOnly(java.nio.file.Path)).
1515
* GR-22699(EE-only) Added the ability to spawn `Engine` or `Context` isolated in a separate process by setting `Context.Builder.option("engine.IsolateMode", "external").`.
1616
* GR-64087 Removed the dependency on `org.graalvm.truffle:truffle-enterprise` from all language and tool POM artifacts. As a result, the community Maven artifacts (those with an artifact ID ending in `-community`) are now identical to their corresponding non-community artifacts. Consequently, all community language and tool POM artifacts have been deprecated. The only exception is `org.graalvm.truffle:java-community` vs. `org.graalvm.truffle:java`, which differ in the bundled Java runtime. Embedders using auxiliary engine caching, polyglot isolates, a isolated/untrusted sandbox policy, or the sandbox resource limits must now explicitly add the `org.graalvm.truffle:truffle-enterprise` Maven artifact to the classpath or module path.
17+
* GR-66339 Truffle now checks that its multi-release classes ([JEP 238](https://openjdk.org/jeps/238)) are loaded correctly and provides a descriptive error message if they are not.
1718

1819
## Version 24.2.0
1920
* GR-54905 When using Truffle NFI with the Panama backend, native access must now be granted to the Truffle module instead of the NFI Panama module. Use the `--enable-native-access=org.graalvm.truffle` Java command line option to enable the native access for the NFI Panama backend.

truffle/mx.truffle/suite.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,22 @@
238238
"graalCompilerSourceEdition": "ignore",
239239
},
240240

241+
# This uses the lowest Multi-Release version possible,
242+
# for checking that Multi-Release classes are used as expected (see CheckMultiReleaseSupport).
243+
"com.oracle.truffle.api.jdk9" : {
244+
"subDir" : "src",
245+
"sourceDirs" : ["src"],
246+
"dependencies" : [
247+
],
248+
"overlayTarget" : "com.oracle.truffle.api",
249+
"checkPackagePrefix" : "false",
250+
"multiReleaseJarVersion" : "9",
251+
"checkstyle" : "com.oracle.truffle.api",
252+
"javaCompliance" : "9+",
253+
"workingSets" : "API,Truffle",
254+
"graalCompilerSourceEdition": "ignore",
255+
},
256+
241257
"com.oracle.truffle.api.jdk21" : {
242258
"subDir" : "src",
243259
"sourceDirs" : ["src"],
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.truffle.api.impl;
42+
43+
public abstract class CheckMultiReleaseSupport {
44+
45+
private CheckMultiReleaseSupport() {
46+
}
47+
48+
public static boolean isSupported() {
49+
return true;
50+
}
51+
52+
}

truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import java.util.ServiceLoader;
4949
import java.util.Set;
5050

51+
import com.oracle.truffle.api.impl.CheckMultiReleaseSupport;
5152
import com.oracle.truffle.api.impl.DefaultTruffleRuntime;
5253

5354
/**
@@ -105,6 +106,14 @@ private static TruffleRuntimeAccess selectTruffleRuntimeAccess(List<Iterable<Tru
105106
}
106107

107108
private static TruffleRuntime createRuntime() throws InternalError {
109+
if (!CheckMultiReleaseSupport.isSupported() && !Boolean.getBoolean("polyglotimpl.DisableMultiReleaseCheck")) {
110+
throw new InternalError("Truffle could not be initialized because Multi-Release classes are not configured correctly. " +
111+
"This most likely means Truffle classes have been repackaged incorrectly and the `Multi-Release: true` attribute in META-INF/MANIFEST.MF has been lost. " +
112+
"A common cause of this error is invalid Uber JAR configuration. " +
113+
"For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#uber-jar-file-creation. " +
114+
"This check may be disabled with '-Dpolyglotimpl.DisableMultiReleaseCheck=true'.");
115+
}
116+
108117
if (Boolean.getBoolean("truffle.UseFallbackRuntime")) {
109118
return new DefaultTruffleRuntime("The fallback runtime was explicitly selected using the -Dtruffle.UseFallbackRuntime option.");
110119
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.truffle.api.impl;
42+
43+
/*
44+
* Implementation internal class. Please do not use.
45+
*/
46+
public abstract class CheckMultiReleaseSupport {
47+
48+
private CheckMultiReleaseSupport() {
49+
}
50+
51+
public static boolean isSupported() {
52+
return false;
53+
}
54+
55+
}

0 commit comments

Comments
 (0)