GraalVM Community Edition 25

(2025-09-16)

Platform and Distributions

Features

Graal Compiler

  • Implemented initial optimization of Java Vector API (JEP 338) operations. Load, store, basic arithmetic, reduce, compare, and blend operations are transformed to efficient machine instructions where possible. Coverage of more operations is planned for the future. This optimization is experimental and can be disabled by setting the OptimizeVectorAPI option to false. Vector API operations are supported both on JIT and when building native images.

Native Image

Performance Improvements

  • Enabled Whole-Program Sparse Conditional Constant Propagation (WP-SCCP) 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. Learn more about this optimization in SkipFlow: Producing Smaller Executables with GraalVM.
  • Refined the Graal Neural Network (GraalNN) models for control split profile inference by introducing two specialized variants: a more conservative model for O2 and a more aggressive one for O3. These updates are expected to deliver performance improvements of 1–3% for both O2 and O3 optimization levels, as well as a binary size reduction of over 1% in O2. The new GNN-based control split profile inference is enabled by default in O3. To enable it in O2, pass the option -H:+MLProfileInferenceUseGNNModel.
  • Added an XGBoost-based static profiler for call count profile inference in Native Image. The model classifies methods as either cold or regular/hot, guiding optimizations and reducing binary size with minimal impact on runtime performance. To enable it, use the option: -H:+MLCallCountProfileInference. Not available in GraalVM Community Edition.
  • Added the experimental option -H:+RelativeCodePointers to significantly reduce relocation entries in position-independent executables and shared libraries.

New Features

  • Enhanced support for the Foreign Function & Memory (FFM) API (JEP 454) in Native Image:
    • Platform compatibility – Enabled FFM API (“Panama”) support on macOS AArch64 and Linux AArch64.
    • Introduced a new syntax for configuring the FFM API.
    • Implemented Arena.ofShared() from the FFM API.
    • Added the Tracing agent support for applications using the FFM API. The agent generates the FFM configuration in the reachability-metadata.json file. Additionally, support for FFM configurations has been added to the native-image-configure tool.
    • Added extensive reference documentation for FFM API support in Native Image.
  • Implemented initial optimization support of Java Vector API JEP 338 operations in native images. To enable these optimizations, build native images with the --add-modules jdk.incubator.vector and -H:+VectorAPISupport options.
  • Introduced --future-defaults=[all|run-time-initialize-jdk|<options>|none], which enables options planned to become defaults in future releases. The enabled options are:
    • run-time-initialize-jdk – Shifts from build-time initialization of the JDK to runtime initialization for most components. This transition is gradual, with different JDK components becoming runtime initialized in each release. In this release, it enables run-time-initialize-security-providers and run-time-initialize-file-system-providers. If JDK classes are not stored in the image heap, this option should have no effect. If the option breaks your build, follow the suggestions in the error messages.
    • complete-reflection-types – Ensures that reflective registration of a type (via metadata files or the Feature API) always includes all type metadata. All registered types now behave consistently with types defined in the reachability-metadata.json file.
    • run-time-initialize-security-providers – Shifts from build-time initialization of security providers to runtime initialization. Unless java.security.Provider-related classes are stored in the image heap, this option should have no effect. If it breaks your build, follow the suggestions in the error messages. Run-time initialization of security providers helps reduce image heap size by avoiding unnecessary objects inclusion.
    • run-time-initialize-file-system-providers – Shifts from build-time initialization of java.nio.file.spi.FileSystemProvider to runtime initialization. Unless FileSystemProvider-related classes are stored in the image heap, this option should have no effect. If it breaks your build, follow the suggestions in the error messages.
  • Enabled --install-exit-handlers by default for native executables and deprecated the option. If shared libraries were using this option, the same functionality can be restored by using the -H:+InstallExitHandlers host option.
  • Recurring callback support is no longer enabled by default. To enable this feature, use the -H:+SupportRecurringCallback host option at image build time.
  • Added the experimental option ClassForNameRespectsClassLoader, which makes Class.forName(...) respect the class loader hierarchy.

Improved Security

  • Introduced advanced obfuscation for Native Image — an experimental Oracle GraalVM-only feature that applies symbol obfuscation to enhance protection against reverse engineering by renaming symbols in native images. Advanced obfuscation affects user code and third party dependencies, but not JDK and GraalVM classes, or names required by reachability metadata, annotations, and proxies. To enable the feature, pass -H:AdvancedObfuscation= to the native-image command. Learn more in the reference documentation.
  • A Software Bill of Materials (SBOM) is now embedded by default in native images. To disable the SBOM from being embedded, pass the option --enable-sbom=false. (Not available in GraalVM Community Edition).

Simplified Metadata Configuration

  • Added the experimental option -H:Preserve to instruct the native-image tool to keep entire packages, modules, or all classes on the classpath. For example, if you pass -H:Preserve=package=<package_name>, all of the classes in that package will be available in the native executable, even if static analysis could not discover them. The usage syntax is -H:Preserve=[all|none|module=<module>|package=<package>|package=<package-wildcard>|path=<cp-entry>][,...]. See the example application for this use case.
  • JNI registration is now included as part of the "reflection" section in the reachability-metadata.json file using the "jniAccessible" attribute. Registrations performed through the "jni" section of reachability-metadata.json and through jni-config.json will still be accepted and parsed correctly.
  • Enabled lambda classes to be registered for reflection and serialization in the reachability-metadata.json file. The format is detailed here.
  • Resource bundle registration is now included as part of the "resources" section in the reachability-metadata.json file. When this is the case, the bundle name is specified using the "bundle" field. Find the examples in the documentation.
  • Missing registration errors are now subclasses of LinkageError.
  • Improved handling of invalid class names under --exact-reachability-metadata: Reflection and JNI queries now correctly throw the expected JDK exceptions without requiring metadata entries when the queried class name is clearly invalid.

Experimental Native Image Tracing Agent

  • Added experimental support for a new Native Image Tracing Agent. Unlike the existing tracing agent (which observes application behavior on the JVM), the new agent operates in Native Image mode and is more closely aligned with Native Image semantics.
    • To use the new agent, build your application with -H:Preserve=all (which also enables -H:+MetadataTracing), and then run the executable with -XX:TraceMetadata=path=<trace_output_directory>.
    • The agent will trace the actual types, resources, and other elements required by Native Image, and generate reachability metadata. This metadata can then be used to re-build the application with only the required types and resources.

Platform Compatibility

  • In containers and CI environments, the build process now uses 85% of system memory. Otherwise, it tries to only use available memory. If less than 8GB of memory are available, it falls back to 85% of system memory. The reason for the selected memory limit is now also shown in the build resources section of the build output.

Debugging and Monitoring Improvements

  • Added support for the runtime debug info generation using the option -H:+RuntimeDebugInfo. It adds runtime debugging information into a native image for use with GDB.
  • Added a JVM version check to the Native Image agent. The agent now aborts execution if the JVM major version does not match the version it was built with and issues a warning if the full JVM version differs.
  • Added validation of hosted options passed to native-image before starting the build process. Unknown options are detected early, with suggestions provided to help fix them.
  • Added the experimental -H:+JDWP option.

Deprecated Functionality

  • Deprecated class-level metadata extraction using native-image-inspect and removed the DumpMethodsData option. Instead, use class-level SBOMs by passing --enable-sbom=class-level,export to the native-image builder. The default value of the IncludeMethodData option has been changed to false.
  • Removed the sequential reachability handler. The only remaining variant is the concurrent reachability handler, which has been the default implementation since its introduction. Additionally, the -H:-RunReachabilityHandlersConcurrently option was removed, which had been deprecated in GraalVM for JDK 24.
  • Removed the total number of loaded types, fields, and methods from the Native Image build output, deprecated these metrics in the build output schema, and removed already deprecated build output metrics.
  • Jipher Java Cryptographic Service Provider (JCP) is no longer available as part of the Oracle GraalVM release, but can be downloaded separately from Java Tools and Resources. For more information, see the Jipher JCP reference documentation.

GraalJS

  • Enabled ECMAScript 2025 mode by default.
  • Made the option js.text-encoding stable and allowed in SandboxPolicy.CONSTRAINED.
  • Enabled source phase imports from WebAssembly modules (import source mod from "./mod.wasm") by default if the js.webassembly option is enabled, and the js.source-phase-imports option is not explicitly set to false.
  • Implemented several ECMAScript proposals:
  • Updated Node.js to version 22.17.1.

GraalPy

Improvements and New Features

  • Updated the Python standard library and core to version 3.12.8.
  • The full-featured Python REPL is now available on GraalPy standalone builds for Windows.
  • The sys.implementation.version call now returns the GraalPy version instead of the Python version it implements. Additionally, the GraalPy version is available as sys.graalpy_version_info for easier discovery, especially by users familiar with PyPy’s sys.pypy_version_info.
  • The GRAALPY_VERSION_NUM C macro now includes the release level and serial number to fully conform to the hexversion format, without breaking existing version comparisons.
  • The dir(foreign_object) call now returns both foreign methods and Python methods, whereas previously it returned only foreign methods.
  • Added support for the __name__, __doc__, and __text_signature__ attributes on foreign executables, enabling better integration with Python-side introspection. This is useful, for example, when using Java functional interfaces in place of Python functions—such as with LangChain’s @tool annotation that inspects underlying functions.
  • Implemented faulthandler.dump_traceback_later to enhance support for testing frameworks that handle resilience to crashes.
  • Added support for sharing Arrow arrays and tables between Java, PyArrow, and Pandas, reducing data copying when embedding these libraries into Java projects.
  • Enabled FTS3, FTS4, FTS5, RTREE, and math function features in the bundled SQLite3 library.
  • Added compatibility patches for several libraries and versions, including Torch 2.7.0, PyGObject 3.52.3, xmlschema 4.0.0, lxml (below 5.4.0), SciPy 1.15, jq 1.8.0, NumPy (below 2.3), ormsgpack (below 1.9.1), pandas 2.2.3, PyArrow 19.0, and PyMuPDF 1.25.4.

Removed Functionality

  • Removed support for running C extensions as LLVM bitcode. This also removes the related options python.UseSystemToolchain and python.NativeModules. Isolation of native code when embedding GraalPy into Java projects is now provided by the Oracle GraalVM polyglot isolate feature, which can launch in a separate external sub-process by setting the --engine.IsolateMode=external option.
  • Removed the built-in HPy module. HPy can now be installed and used from its upstream sources.

Platform Compatibility

  • Fixed several issues affecting cibuildwheel on Windows to make it easier for Python projects to build and distribute native extensions for GraalPy on all supported platforms.
  • The GraalPy Native standalone on Linux now uses the G1 garbage collector which is much faster.

GraalWasm

  • Context.eval now returns a compiled (but not yet instantiated) module object, rather than a module instance. To instantiate the module, call newInstance() on the returned module object. For example:
    Context c = Context.create();
    Source wasmSource = Source.newBuilder(...).build();
    Value module = c.eval(wasmSource);
    Value instance = module.newInstance(); // prior to 25.0: c.eval(wasmSource)
    
    • This change allows a single compiled module to be instantiated multiple times and run independently within the same context. Previously, each module could only be instantiated once per context.
    • The newInstance() method optionally accepts an import object (similar to the WebAssembly JavaScript API), as well as other modules to link together.
    • To restore the previous behavior, pass the experimental option --wasm.EvalReturnsInstance=true to the builder.
    • Note that modules instantiated via module.newInstance() are not accessible through context.getBindings("wasm"), unlike modules instantiated directly using context.eval when the --wasm.EvalReturnsInstance=true option is used.
  • Exports are no longer exposed as direct members of the module instance. Instead, use the exports member of the module instance to access its exports. For example:
    Value mainFunction = instance.getMember("exports").getMember("main"); // prior to 25.0: instance.getMember("main")
    

    This change aligns the API with the WebAssembly JavaScript API and makes it possible to introduce other members on the module instance without name clashes. For more details and migration examples, see the GraalWasm Polyglot API Migration Guide and the project README.

  • Implemented support for editing primitive values during debugging. Fixed several debugger-related issues.
  • Implemented the WebAssembly SIMD proposal using the JDK’s Vector API. This improves peak performance when running WebAssembly code that makes heavy use of SIMD instructions. The new implementation is always enabled in native images. On the JVM, it is opt-in and requires setting --add-modules=jdk.incubator.vector. Because the Vector API is incubating, enabling it will print the following warning to stderr:
    WARNING: Using incubator modules: jdk.incubator.vector
    

Espresso

  • Added support for guest Java version 25.
  • Added experimental support for -javaagent. The support for java agents helps integrate with various IDEs, debuggers, and so on. It can also be enabled via the Polyglot API by setting the option java.JavaAgent.$i to /path/to/jar=agent-options, where $i starts at 0 and increments by 1 for each additional Java agent.
  • Added the org.graalvm.continuations.IdentityHashCodes class, which provides utilities to restore identity hash codes. This can be used to improve deserialization of continuations.
  • Introduced the EnableAdvancedRedefinition option, which controls whether features such as method or field addition/removal and class hierarchy changes are enabled. This option controls access to these capabilities for both JDWP and Java agents. Previously, this functionality was enabled by default for JDWP; in this release, it must now be explicitly turned on.
  • Added experimental support for JVMCI, which can be enabled with the java.EnableJVMCI option.

Polyglot Runtime

  • All language and tool POMs artifacts are now OSS licensed. It means:
    • The “community” Maven artifacts (those with an artifact ID ending in -community) are now identical to their corresponding “non-community” artifacts.
    • 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 still differ in the bundled Java runtime.
    • Embedders using auxiliary engine caching, polyglot isolates, a isolated or 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.
  • Improved the memory isolation between multiple isolates, known as Monocle or Software Fault Isolation. Monocle is a new mitigation for speculative execution attacks for runtime-compiled code running inside GraalVM isolates. With Monocle enabled, every load generated from untrusted code is either (a) masked so it cannot address memory outside its own isolate heap, or (b) guarded by a lightweight fence when masking is impossible. This keeps one isolate from speculatively reading data belonging to another isolate in the same GraalVM process. Monocle is about 4x faster compared to the previous, fence-based mitigation, while delivering the same security guarantees. It is available for the AMD64 architecture and can be enabled with -R:+MemoryMaskingAndFencing. Monocle is used for polyglot isolates. As a result, sandboxed code execution is faster.
  • The option sandbox.MaxStackFrames is no longer mandatory for the UNTRUSTED polyglot sandbox policy, due to improved deoptimization handling in compiled code. Removing the option significantly improves performance of the sandboxed code.
  • The WebAssembly (Wasm) language is now available as a polyglot isolate under the name wasm-isolate on Maven Central. Wasm is now supported for untrusted code execution (all three are polyglot isolates related).

Find a complete list of updates in the changelog.

Truffle Framework

  • Added the deoptimization cycle detection feature, which is enabled by default. When a deoptimization cycle is detected, the compilation fails with a permanent bailout that includes the Java stack trace of the problematic location. If this error is encountered too frequently it can be disabled by setting compiler.DeoptCycleDetectionThreshold to -1. For further information, see the Automatic Detection of Deoptimization Cycles guide.
  • Implemented the extended Dynamic Object Model Layout that adds:
    • A shape obsolescence strategy enabling optimistic type speculation for primitive property values. When speculation fails, shapes gradually migrate to more general forms (for example, moving primitive slots to reference slots), eventually converging on a stable, general shape tree. This reduces shape polymorphism by replacing overly specific shapes with more general ones.
    • Automatic reference type tracking based on assumptions, which eliminates redundant type checks.
    • Automatic single-assignment tracking based on assumptions allowing languages to assume that a property is effectively final (i.e. stays unchanged after the initial assignment) as well as constant-fold values of a constant receiver with a known shape.
    • You can still disable the new layout and switch back to the previous implementation using the system property -Dtruffle.object.LayoutFactory=com.oracle.truffle.api.object.CoreLayoutFactory.
  • Enabled lazy deoptimization of runtime-compiled code by default for native-image hosts, which reduces memory used for deoptimization. It can be turned off using the -H:-LazyDeoptimization option.
  • Now you can specify language and instrument specific options using Source.Builder.option(String, String). Languages may describe available source options by implementing the methods TruffleLanguage.getSourceOptionDescriptors() and TruffleInstrument.getSourceOptionDescriptors() respectively.
  • Added multiple improvements to Bytecode DSL:
    • Improved builder performance: creating bytecode nodes is now 40% faster and requires five times less temporary memory.
    • Builder instances now implement toString(), which prints both the current operations and the instructions already emitted. This should make debugging builder usage easier.
    • Improved variadic support: variadic operands now compile and execute more efficiently, with fewer reallocations.
    • Added a startOffset parameter to @Variadic, allowing reservation of a fixed number of slots in the object array for custom use. The @Variadic annotation can now also be applied to @Operation-annotated classes to indicate that the operation produces a dynamic variadic return value. Dynamic @Variadic return values are efficiently flattened into the object array of a @Variadic operand.
    • Added a variadicStackLimit parameter to @GenerateBytecode that allows to specify how many variable arguments are stored on the stack before they are collapsed into an object array.

Find a complete list of updates in the Truffle changelog.

Connect with us