oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://www.graalvm.org
Other
20.38k stars 1.64k forks source link

Unable to use GraalVM v21 SDK with native image at runtime #7825

Closed mmoayyed closed 11 months ago

mmoayyed commented 12 months ago

Describe the issue

Unable to use GraalVM SDK APIs when native image runs. For example, I see:

Caused by: java.lang.NoClassDefFoundError: org.graalvm.home.Version
    at org.apereo.cas.nativex.CasNativeBannerContributor.<clinit>(CasNativeBannerContributor.java:17)
    at java.base@21.0.1/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
    at java.base@21.0.1/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
    at java.base@21.0.1/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:789)
    ... 13 common frames omitted

Note that the native image builds and compiles OK. The offending class simply does this:

import org.apereo.cas.util.spring.boot.BannerContributor;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.graalvm.home.Version;
import org.springframework.core.env.Environment;
import java.util.Formatter;

public class CasNativeBannerContributor implements BannerContributor {
    private static final String GRAALVM_VERSION = Version.getCurrent().toString();

    @Override
    public void contribute(final Formatter formatter, final Environment environment) {
        val javaVendor = System.getProperty("java.vendor.version");
        if (StringUtils.isNotBlank(javaVendor)) {
            formatter.format("Graal VM SDK Version: %s%n", GRAALVM_VERSION);
        }
    }
}

Steps to reproduce the issue

git clone --branch=master --depth=1 https://github.com/mmoayyed/cas.git
cd cas
chmod +x ./ci/tests/native/build.sh && ./ci/tests/native/build.sh

Describe GraalVM and your environment:

java version "21.0.1" 2023-10-17
Java(TM) SE Runtime Environment Oracle GraalVM 21.0.1+12.1 (build 21.0.1+12-jvmci-23.1-b19)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 21.0.1+12.1 (build 21.0.1+12-jvmci-23.1-b19, mixed mode, sharing)

More details

[native-image-plugin] GraalVM Toolchain detection is disabled
[native-image-plugin] GraalVM location read from environment variable: JAVA_HOME
[native-image-plugin] Native Image executable path: /Library/Java/JavaVirtualMachines/graalvm/Contents/Home/lib/svm/bin/native-image
Warning: The option '-H:ReflectionConfigurationResources=META-INF/native-image/org.apache.tomcat.embed/tomcat-embed-el/tomcat-reflection.json' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:+BuildReport' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:+InlineBeforeAnalysis' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:ResourceConfigurationResources=META-INF/native-image/org.apache.tomcat.embed/tomcat-embed-core/tomcat-resource.json' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:ReflectionConfigurationResources=META-INF/native-image/org.apache.tomcat.embed/tomcat-embed-core/tomcat-reflection.json' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:ResourceConfigurationResources=META-INF/native-image/org.apache.tomcat.embed/tomcat-embed-el/tomcat-resource.json' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:+TraceSecurityServices' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: Please re-evaluate whether any experimental option is required, and either remove or unlock it. The build output lists all active experimental options, including where they come from and possible alternatives. If you think an experimental option should be considered as stable, please file an issue.
========================================================================================================================
GraalVM Native Image: Generating 'cas' (executable)...
========================================================================================================================
For detailed information and explanations on the build output, visit:
https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/BuildOutput.md
------------------------------------------------------------------------------------------------------------------------
Warning: Using -g is not supported on macOS
Registering class entries and packages for initialization at build-time
Registering BouncyCastle security provider
The URL protocol jar is not tested and might not work as expected.
Supported URL protocols enabled by default: file,resource. Supported URL protocols available on demand: http,https.
The URL protocol file is enabled by default. The option --enable-url-protocols=file is not needed.
The URL protocol resource is enabled by default. The option --enable-url-protocols=resource is not needed.
[1/8] Initializing...                                                                                    (7.2s @ 0.78GB)
 Java version: 21.0.1+12, vendor version: Oracle GraalVM 21.0.1+12.1
 Graal compiler: optimization level: b, target machine: native, PGO: off
 C compiler: cc (apple, arm64, 15.0.0)
 Garbage collector: Serial GC (max heap size: 80% of RAM)
 6 user-specific feature(s):
 - com.oracle.svm.polyglot.groovy.GroovyIndyInterfaceFeature
 - com.oracle.svm.thirdparty.gson.GsonFeature
 - org.apereo.cas.nativex.features.BouncyCastleProviderFeature
 - org.eclipse.angus.activation.nativeimage.AngusActivationFeature
 - org.eclipse.angus.mail.nativeimage.AngusMailFeature
 - org.springframework.aot.nativex.feature.PreComputeFieldFeature
------------------------------------------------------------------------------------------------------------------------
 4 experimental option(s) unlocked:
 - '-H:+BuildReport' (origin(s): command line)
 - '-H:ResourceConfigurationResources' (origin(s): 'META-INF/native-image/org.apache.tomcat.embed/tomcat-embed-core/native-image.properties' in 'file:///Users/misagh/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/10.1.15/tomcat-embed-core-10.1.15.jar', 'META-INF/native-image/org.apache.tomcat.embed/tomcat-embed-el/native-image.properties' in 'file:///Users/misagh/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/10.1.15/tomcat-embed-el-10.1.15.jar')
 - '-H:+TraceSecurityServices' (origin(s): command line)
 - '-H:ReflectionConfigurationResources' (origin(s): 'META-INF/native-image/org.apache.tomcat.embed/tomcat-embed-core/native-image.properties' in 'file:///Users/misagh/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/10.1.15/tomcat-embed-core-10.1.15.jar', 'META-INF/native-image/org.apache.tomcat.embed/tomcat-embed-el/native-image.properties' in 'file:///Users/misagh/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/10.1.15/tomcat-embed-el-10.1.15.jar')
------------------------------------------------------------------------------------------------------------------------
Build resources:
 - 10.67GB of memory (16.7% of 64.00GB system memory, set via '-Xmx12G')
 - 10 thread(s) (100.0% of 10 available processor(s), determined at start)
# Printing compilation-target information to: /Users/misagh/Workspace/GitWorkspace/cas-server/webapp/cas-server-webapp-native/build/native/nativeCompile/reports/target_info_20231114_153737.txt
# Printing security services automatic registration to: /Users/misagh/Workspace/GitWorkspace/cas-server/webapp/cas-server-webapp-native/build/native/nativeCompile/reports/security_services_20231114_153740.txt
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
Found pending operations, continuing analysis.
# Printing native-library information to: /Users/misagh/Workspace/GitWorkspace/cas-server/webapp/cas-server-webapp-native/build/native/nativeCompile/reports/native_library_info_20231114_153834.txt
[2/8] Performing analysis...  [*******]                                                                 (57.3s @ 5.00GB)
   46,051 reachable types   (93.1% of   49,450 total)
   67,338 reachable fields  (67.8% of   99,326 total)
  236,733 reachable methods (70.2% of  337,374 total)
   16,097 types, 2,655 fields, and 34,677 methods registered for reflection
       64 types,    66 fields, and    55 methods registered for JNI access
        5 native libraries: -framework CoreServices, -framework Foundation, dl, pthread, z
[3/8] Building universe...                                                                              (11.5s @ 4.19GB)
[4/8] Parsing methods...      [**]                                                                       (4.6s @ 5.00GB)
[5/8] Inlining methods...     [****]                                                                     (2.1s @ 5.89GB)
[6/8] Compiling methods...    [****]                                                                    (19.2s @ 3.27GB)
[7/8] Layouting methods...    [***]                                                                     (11.0s @ 3.85GB)
[8/8] Creating image...       [****]                                                                    (15.9s @ 5.24GB)
  76.02MB (31.14%) for code area:   169,197 compilation units
 165.86MB (67.95%) for image heap:1,074,706 objects and 6,088 resources
   2.22MB ( 0.91%) for other data
 244.10MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 origins of code area:                                Top 10 object types in image heap:
  12.88MB java.base                                           81.41MB byte[] for embedded resources
   8.10MB svm.jar (Native Image)                              25.03MB byte[] for code metadata
   5.08MB bcprov-jdk18on-1.76.jar                             15.90MB byte[] for java.lang.String
   4.83MB groovy-4.0.15.jar                                    9.80MB java.lang.Class
   3.84MB tomcat-embed-core-10.1.15.jar                        7.13MB java.lang.String
   3.57MB java.xml                                             4.42MB char[]
   1.61MB caffeine-3.1.8.jar                                   4.20MB byte[] for reflection metadata
   1.52MB jackson-databind-2.15.3.jar                          2.11MB com.oracle.svm.core.hub.DynamicHubCompanion
   1.48MB java.desktop                                         1.32MB c.o.svm.core.hub.DynamicHub$ReflectionMetadata
   1.28MB aspectjweaver-1.9.20.1.jar                           1.16MB java.lang.Object[]
  30.89MB for 320 more packages                               13.38MB for 8869 more object types
                                    For more details, open 'cas-build-report.html'.
------------------------------------------------------------------------------------------------------------------------
Security report:
 - Binary includes Java deserialization.
 - Use '--enable-sbom' to embed a Software Bill of Materials (SBOM) in the binary.
------------------------------------------------------------------------------------------------------------------------
Recommendations:
 PGO:  Use Profile-Guided Optimizations ('--pgo') for improved throughput.
 INIT: Adopt '--strict-image-heap' to prepare for the next GraalVM release.
 AWT:  Use the tracing agent to collect metadata for AWT.
 HEAP: Set max heap for improved and more predictable memory usage.
------------------------------------------------------------------------------------------------------------------------
                       14.7s (11.2% of total time) in 104 GCs | Peak RSS: 9.15GB | CPU load: 6.01
------------------------------------------------------------------------------------------------------------------------
Produced artifacts:
 /Users/misagh/Workspace/GitWorkspace/cas-server/webapp/cas-server-webapp-native/build/native/nativeCompile/cas (executable, debug_info)
 /Users/misagh/Workspace/GitWorkspace/cas-server/webapp/cas-server-webapp-native/build/native/nativeCompile/cas-build-report.html (build_info)
 /Users/misagh/Workspace/GitWorkspace/cas-server/webapp/cas-server-webapp-native/build/native/nativeCompile/sources (debug_info)
========================================================================================================================
Finished generating 'cas' in 2m 10s.
[native-image-plugin] Native Image written to: /Users/misagh/Workspace/GitWorkspace/cas-server/webapp/cas-server-webapp-native/build/native/nativeCompile

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.5-rc-1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD SUCCESSFUL in 2m 38s
hamzaGhaissi commented 12 months ago

i was not able to get the project running, can you please share a minimal reproducer

hamzaGhaissi commented 11 months ago

@mmoayyed can you check if you have this dependency implementation("org.graalvm.polyglot:polyglot:23.1.1")

you can check this demo on how to run gradle with jdk 21 https://github.com/graalvm/polyglot-embedding-demo

mmoayyed commented 11 months ago

Thank you.

Yes that dependency does exist, and certainly, the project does compile fine with GraalVM SDK available on the compile classpath. It's only when the native image actually launches that the error does show up. At the moment, I have removed all such references (i.e. org.graalvm.home.Version) from the codebase and the project builds and runs OK but I would like to solve this nonetheless.

Looking at the sample demo, I see that there is:

implementation("org.graalvm.polyglot:polyglot:$graalVMVersion")

My understanding was that such libraries must never be actually included in the final native image. As notes here,

The native image "compile only" configurations can typically be used to declare dependencies which are only required when building a native binary, and therefore shouldn’t leak to the classic "JVM" runtime.

Is this not true, or am I misunderstanding this?

hamzaGhaissi commented 11 months ago

@mmoayyed Before Graalvm for jdk 21 The org.graalvm.polyglot module was contained by default in the GraalVM JDK. Starting from GraalVM for jdk 21, To continue using the GraalVM language runtime(s) and other components, use language standalones or specify them as Maven or Gradle dependencies in your project.
see
https://www.graalvm.org/release-notes/JDK_21/ && https://www.graalvm.org/release-notes/JDK_21/#polyglot-embedding

mmoayyed commented 11 months ago

Thank you very much. Defining org.graalvm.polyglot as a Gradle dependency does indeed help.