$ native-image --help
GraalVM native-image building tool
This tool can be used to generate an image that contains ahead-of-time compiled Java code.
Usage: native-image [options] class [imagename] [options]
(to build an image for a class)
or native-image [options] -jar jarfile [imagename] [options]
(to build an image for a jar file)
or native-image [options] -m <module>[/<mainclass>] [options] π MODULE SYSTEM OPTION
native-image [options] --module <module>[/<mainclass>] [options] π MODULE SYSTEM OPTION
(to build an image for a module)
where options include:
@argument files one or more argument files containing options
-cp <class search path of directories and zip/jar files>
-classpath <class search path of directories and zip/jar files>
--class-path <class search path of directories and zip/jar files>
A : separated list of directories, JAR archives,
and ZIP archives to search for class files.
-p <module path> <<< MODULE SYSTEM OPTION
--module-path <module path>... π MODULE SYSTEM OPTION
A : separated list of directories, each directory
is a directory of modules.
--add-modules <module name>[,<module name>...] π MODULE SYSTEM OPTION
root modules to resolve in addition to the initial module.
<module name> can also be ALL-DEFAULT, ALL-SYSTEM,
ALL-MODULE-PATH.
-D<name>=<value> set a system property
....
$ native-image --help-extra
Non-standard options help:
--expert-options lists image build options for experts
--expert-options-all lists all image build options for experts (use at your own risk).
Options marked with [Extra help available] contain help that can be
shown with --expert-options-detail
--expert-options-detail
displays all available help for a comma-separated list of option names.
Pass * to show extra help for all options that contain it.
--add-exports value <module>/<package>=<target-module>(,<target-module>)* π MODULE SYSTEM OPTION
updates <module> to export <package> to <target-module>,
regardless of module declaration. <target-module> can be
ALL-UNNAMED to export to all unnamed modules.
--add-opens value <module>/<package>=<target-module>(,<target-module>)* π MODULE SYSTEM OPTION
updates <module> to open <package> to <target-module>, regardless
of module declaration.
--add-reads value <module>=<target-module>(,<target-module>)* updates <module> π MODULE SYSTEM OPTION
to read <target-module>, regardless of module declaration.
<target-module> can be ALL-UNNAMED to read all unnamed modules.
--upgrade-module-path <module path>... π Would we ever need this?
A : separated list of directories, each directory
is a directory of modules that replace upgradeable
modules in the runtime image
--enable-native-access <module name>[,<module name>...] π JEP 412 (JDK 17)
modules that are permitted to perform restricted native operations.
<module name> can also be ALL-UNNAMED.
--limit-modules <module name>[,<module name>...]
limit the universe of observable modules
--patch-module <module>=<file>(:<file>)*
override or augment a module with classes and resources
in JAR files or directories.
Remaining options will be added on demand (if the need arises)
resource-config.json
{ "resources": { "includes": [ { "pattern": "^resource-file.txt$" } ] }, "bundles": [ {"name": "your.pkg.Bundle"} ] }
With module support we can use:
-
resource-config.json
{ "resources": { "includes": [ { "pattern": "library-module:^resource-file.txt$" π } ] }, "bundles": [ {"name": "main-module:your.pkg.Bundle"} π ] }
-
Include
resource-file.txt
only from Java module library-module. Even if other modules or classpath contains resources that would match pattern ^resource-file.txt$ -
Using
<module-name>:
ensures module is available at runtime (even if not referenced anywhere else)/* Get resource from module <module-name> */ InputStream resource = ModuleLayer.boot().findModule(<module-name>).getResourceAsStream(resourcePath);
-
Resources / Resource Bundles are per module
Suppose you have:
public static final class MyFeature implements Feature { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { ResourcesRegistry registry = ImageSingletons.lookup(ResourcesRegistry.class); for (Module module : ModuleLayer.boot().modules()) { registry.addResources(ConfigurationCondition.alwaysTrue(), module.getName() + ":" + "module-info.class"); } } }
Using the following at image runtime:
Enumeration<URL> urlEnumeration = null; try { urlEnumeration = ClassLoader.getSystemResources("module-info.class"); π } catch (IOException e) { Assert.fail("IOException in ClassLoader.getSystemResources(\"module-info.class\"): " + e.getMessage()); }
The Enumeration<URL> contains all
module-info.class
resources registered via Feature at build-time!
- Previously the image builder was always running on classpath
$ native-image -jar HelloMaven/target/app-1.0-SNAPSHOT.jar --verbose Executing [ /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/bin/java \ ... --add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED \ --add-exports=java.base/jdk.internal.access.foreign=ALL-UNNAMED \ --add-exports=java.base/jdk.internal.event=ALL-UNNAMED \ --add-exports=java.base/jdk.internal.loader=ALL-UNNAMED \ --add-exports=java.base/jdk.internal.logger=ALL-UNNAMED \ --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED \ ... -cp \ /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/svm.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/objectfile.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/pointsto.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/native-image-base.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/svm-enterprise.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/svm-llvm.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/llvm-wrapper-shadowed.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/javacpp-shadowed.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/llvm-platform-specific-shadowed.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/svm-enterprise-llvm.jar \ --module-path \ /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/truffle/truffle-api.jar \ 'com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus' \ ... -imagecp \ /home/pwoegere/OLabs/issues/HelloMaven/target/app-1.0-SNAPSHOT.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/library-support.jar \ ... ]
- When -p / --module-path is used the builder runs on module-path
$ native-image -p HelloMavenModule/target/app-1.0-SNAPSHOT.jar -m app.hello/paw.App --verbose Executing [ /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/bin/java \ ... --add-exports=java.base/com.sun.crypto.provider=org.graalvm.nativeimage.builder \ π OPENING UP MODULES TOWARDS SPECIFIC TARGET-MODULES --add-exports=java.base/jdk.internal.access.foreign=org.graalvm.nativeimage.builder \ --add-exports=java.base/jdk.internal.event=org.graalvm.nativeimage.builder \ --add-exports=java.base/jdk.internal.loader=org.graalvm.nativeimage.builder \ --add-exports=java.base/jdk.internal.logger=org.graalvm.nativeimage.builder \ --add-exports=java.base/jdk.internal.misc=org.graalvm.nativeimage.builder \ ... --module-path \ π BUILDER RUNS ON EXCLUSIVELY ON MODULE-PATH /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/truffle/truffle-api.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/svm.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/objectfile.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/pointsto.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/native-image-base.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/svm-enterprise.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/svm-llvm.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/llvm-wrapper-shadowed.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/javacpp-shadowed.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/llvm-platform-specific-shadowed.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/builder/svm-enterprise-llvm.jar \ --module \ org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner \ π BUILDER ENTRY POINT IS MODULE/MAINCLASS ... -imagemp \ π MODULE TO BUILD AN IMAGE FROM IS PASSED TO BUILDER VIA -IMAGECP /home/pwoegere/OLabs/issues/HelloMavenModule/target/app-1.0-SNAPSHOT.jar: /home/pwoegere/.local/graalvm/graalvm-ee-java17-22.0.0.1/lib/svm/library-support.jar \ ... ]
- What to expect in the future (the current plan):
- GraalVM 22.2: Switch to running builder on module-path per default.
- GraalVM 22.3: Remove code needed to run builder on classpath.
-
Fix all module access issues when running builder on module-path
e.g. mx native-unittest βbuilder-on-modulepath needs to work for every usecase
-
Build key-GraalVM components on module-path
We already build all GraalVM release native-images coming from the substratevm-suite on module-path
$ git grep -B 1 -A 1 use_modules mx.substratevm/mx_substratevm.py-868- mx_sdk_vm.LauncherConfig( mx.substratevm/mx_substratevm.py:869: use_modules='image', π BUILD IMAGE AS JAVA-MODULE mx.substratevm/mx_substratevm.py-870- main_module="org.graalvm.nativeimage.driver", π DEFINE THE MAIN MODULE -- mx.substratevm/mx_substratevm.py-879- mx_sdk_vm.LibraryConfig( mx.substratevm/mx_substratevm.py:880: use_modules='image', π BUILD IMAGE AS JAVA-MODULE mx.substratevm/mx_substratevm.py-881- destination="<lib:native-image-agent>", -- mx.substratevm/mx_substratevm.py-893- mx_sdk_vm.LibraryConfig( mx.substratevm/mx_substratevm.py:894: use_modules='image', π BUILD IMAGE AS JAVA-MODULE mx.substratevm/mx_substratevm.py-895- destination="<lib:native-image-diagnostics-agent>", -- mx.substratevm/mx_substratevm.py-1063- mx_sdk_vm.LauncherConfig( mx.substratevm/mx_substratevm.py:1064: use_modules='image', π BUILD IMAGE AS JAVA-MODULE mx.substratevm/mx_substratevm.py-1065- main_module="org.graalvm.nativeimage.configure", π DEFINE THE MAIN MODULE
-
But:
- Currently, libgraal cannot be built on module-path
- Also truffle images cannot be built on module-path (except for js)
-
ModuleLayer.boot()
at image runtime cannot simply return the same results asModuleLayer.boot()
at image buildtime -
c.o.svm.hosted.ModuleLayerFeature
takes care of that:- After analysis, we collect reachable modules via classes that are seen as reachable
- We create corresponding runtime-modules and install them in image BootModuleLayer
- As part of that module accessibility settings (
--add-exports
,--add-opens
, ...) are translated from hosted modules to runtime modules (e.g. Resource bundle reflective instantiation)
-
Support for runtime module creation and dynamic visibility changes (even needed by JDK code itself β e.g. XSLT processor generates modules at runtime)
-
Running
mx hellomodule
tests this feature (among others) -
Module aware stack-traces (WIP):
Instead of:
com.foo.bar.App.run(App.java:12) org.acme.Lib.test(Lib.java:80)
We will have:
com.foo.loader//com.foo.bar.App.run(App.java:12) π DEFINED IN THE UNNAMED MODULE OF THE CLASS LOADER NAMED COM.FOO.LOADER acme@2.1/org.acme.Lib.test(Lib.java:80) π DEFINED IN ACME MODULE LOADED BY A BUILT-IN CLASS LOADER
See PR: oracle/graal#4243
- Currently native-image only supports compiling one class for a given fully qualified classname
- Full module-system support needs to get rid of this limitation (classes that are module-private can have identical fully qualified classnames)
- This needs to be fixed at some point.
- Building with the llvm backend does currently only work when the builder runs on classpath
- Demo: Make llvm backend usable with module-path:
vs.native-image -H:CompilerBackend=llvm HelloWorld β
native-image -H:CompilerBackend=llvm --macro:native-image-launcher π₯