|
| 1 | +--- |
| 2 | +layout: docs |
| 3 | +toc_group: build-overview |
| 4 | +link_title: Native Image Layers |
| 5 | +permalink: /reference-manual/native-image/overview/NativeImageLayers/ |
| 6 | +--- |
| 7 | + |
| 8 | +# Native Image Layers |
| 9 | + |
| 10 | +The Native Image Layers feature allows splitting an application and its required libraries into separate binaries: a |
| 11 | +thin layer executable supported by a chain of shared libraries. |
| 12 | +In contrast to regular Native Image building, this mode of operation enables sharing common libraries and VM/JDK code |
| 13 | +between multiple applications, resulting in reduced memory usage at run time. |
| 14 | +Moreover, it reduces the time to build an application since shared layers are only built once. |
| 15 | + |
| 16 | +> Note this feature is experimental and under development. |
| 17 | +
|
| 18 | +### Table of Contents |
| 19 | + |
| 20 | +* [Native Image Layers Architecture](#native-image-layers-architecture) |
| 21 | +* [Creating Native Image Layers](#creating-native-image-layers) |
| 22 | +* [Packaging Native Image Layers](#packaging-native-image-layers) |
| 23 | + |
| 24 | +## Native Image Layers Architecture |
| 25 | + |
| 26 | +When using Native Image Layers an application is logically composed of the final application executable plus one or more |
| 27 | +supporting layers containing code that the application requires. |
| 28 | +The supporting layers are called _shared layers_ and the application executable is referred to as either the |
| 29 | +_application layer_ or _executable layer_. |
| 30 | +The _initial_ or _base_ layer is a shared layer containing VM internals and core _java.base_ functionality at a minimum. |
| 31 | +It can also contain modules specific to a certain framework that the application may be built upon. |
| 32 | +We refer to any subsequent layer built on top of a shared layer as an _extension layer_. |
| 33 | + |
| 34 | +At run time a shared layer is a shared object file on which other intermediate layers or executable application |
| 35 | +layers can be dependent. |
| 36 | +Thus, the application and its supporting shared layers form a chain: |
| 37 | + |
| 38 | +```shell |
| 39 | +base-layer.so # initial layer (includes VM/JDK code) |
| 40 | +└── mid-layer.so # intermediate layer, depends on base-layer.so, adds extra functionality |
| 41 | + └── executable-image # final application executable, depends on mid-layer.so and base-layer.so |
| 42 | +``` |
| 43 | + |
| 44 | +This architecture enables the sharing of layers between applications when the hierarchy of layers forms a tree structure. |
| 45 | +For example, at run time there could be four applications that share one base layer and two intermediate layers: |
| 46 | + |
| 47 | +```shell |
| 48 | +base-layer.so # initial layer (includes VM/JDK code) |
| 49 | +├── executable-image-0 # final application executable, depends on base-layer.so |
| 50 | +├── mid-layer-0.so # intermediate layer, depends on base-layer.so, adds extra functionality |
| 51 | +│ ├── executable-image-00 # final application executable, depends on mid-layer-0.so and base-layer.so |
| 52 | +│ └── executable-image-01 # final application executable, depends on mid-layer-0.so and base-layer.so |
| 53 | +└── mid-layer-1.so # intermediate layer, depends on base-layer.so, adds extra functionality |
| 54 | + └── executable-image-10 # final application executable, depends on mid-layer-1.so and base-layer.so |
| 55 | +``` |
| 56 | + |
| 57 | +> Note: The current implementation is limited to only a base layer and an application layer. |
| 58 | +
|
| 59 | +## Creating Native Image Layers |
| 60 | + |
| 61 | +> Note: The API options described in this section are experimental and not yet released. |
| 62 | +> To interact with layers you must currently use their hosted variant: -H:LayerCreate and -H:LayerUse. |
| 63 | +
|
| 64 | +To create and use layers `native-image` accepts two options: `--layer-create` and `--layer-use`. |
| 65 | + |
| 66 | +First, `--layer-create` builds an image layer archive from code available on the class or module path: |
| 67 | + |
| 68 | +``` |
| 69 | +--layer-create=[layer-file.nil][,module=<module-name>][,package=<package-name>] |
| 70 | + builds an image layer file from the modules and packages specified by "module" and "package". |
| 71 | + The file name, if specified, must be a simple file name, i.e., not contain any path separators, |
| 72 | + and have the *.nil extension. Otherwise, the layer-file name is derived from the image name. |
| 73 | + This will generate a Native Image Layers archive file containing metadata required to build |
| 74 | + either another layer or a final application executable that depends on this layer. |
| 75 | + The archive also contains the shared object file corresponding to this layer. |
| 76 | + If this options is specified with an empty value then it disables any prior layer creation option on the command line. |
| 77 | +``` |
| 78 | + |
| 79 | +A layer archive file has a _.nil_ extension, acronym for **N**ative **I**mage **L**ayer. |
| 80 | + |
| 81 | +Second, `--layer-use` consumes a shared layer, and can extend it or create a final executable: |
| 82 | + |
| 83 | +``` |
| 84 | +--layer-use=layer-file.nil |
| 85 | + loads the given layer archive and makes it available to the build process. |
| 86 | + If option --layer-create=another-layer.nil is specified this creates a new layer that depends on the loaded layer. |
| 87 | + If no other layer option is specified this creates a final application executable that depends on the loaded layer. |
| 88 | + If this options is specified with an empty value then it disables any prior layer application option on the command line. |
| 89 | +``` |
| 90 | + |
| 91 | +Specifying each option more than once is allowed, however all but the last instance is ignored. |
| 92 | +Passing an empty value will disable the option, overwriting any previous value. |
| 93 | +These capabilities are useful in builds with long dependency chains where one may want to overwrite or disable layer |
| 94 | +related options from a library dependency. |
| 95 | + |
| 96 | +#### Example Layers Option Usage |
| 97 | + |
| 98 | +```shell |
| 99 | +# given an application that would usually be built like this |
| 100 | +native-image --module-path target/AwesomeLib-1.0-SNAPSHOT.jar --another-extra-option -cp . AwesomeHelloWorld |
| 101 | + |
| 102 | +# you can now create a base-layer.nil layer from the java.base and java.awesome.lib modules |
| 103 | +native-image --layer-create=base-layer.nil,module=java.base,module=java.awesome.lib --module-path target/AwesomeLib-1.0-SNAPSHOT.jar |
| 104 | + |
| 105 | +# then build the application on top of the preexisting base layer |
| 106 | +native-image --layer-use=base-layer.nil --module-path target/AwesomeLib-1.0-SNAPSHOT.jar --another-extra-option -cp . AwesomeHelloWorld |
| 107 | + |
| 108 | +# extend the base layer with a mid layer that adds an extra module, chaining the layers together |
| 109 | +native-image --layer-use=base-layer.nil --layer-create=mid-layer.nil,module=java.ultimate.io.lib --module-path target/UltimateIoLib-1.0-SNAPSHOT.jar |
| 110 | + |
| 111 | +# create an executable based on the mid layer (and implicitly on the base layer) and using the additional UltimateAwesomeHelloWorld.class from the classpath |
| 112 | +native-image --layer-use=mid-layer.nil --module-path target/AwesomeLib-1.0-SNAPSHOT.jar:target/UltimateIoLib-1.0-SNAPSHOT.jar -cp . UltimateAwesomeHelloWorld |
| 113 | + |
| 114 | +# the same application can be built directly on the base-layer.nil |
| 115 | +native-image --layer-use=base-layer.nil --module-path target/AwesomeLib-1.0-SNAPSHOT.jar:target/UltimateIoLib-1.0-SNAPSHOT.jar -cp . UltimateAwesomeHelloWorld |
| 116 | + |
| 117 | +# again, the same application can be built without any layers |
| 118 | +native-image --module-path target/AwesomeLib-1.0-SNAPSHOT.jar:target/UltimateIoLib-1.0-SNAPSHOT.jar -cp . UltimateAwesomeHelloWorld |
| 119 | + |
| 120 | +# additionally a shared library can be built as a top layer containing the extra C entry points, based on a preexisting layer |
| 121 | +native-image --layer-use=base-layer.nil --module-path target/AwesomeLib-1.0-SNAPSHOT.jar --shared |
| 122 | + |
| 123 | +# or without the layer |
| 124 | +native-image --module-path target/AwesomeLib-1.0-SNAPSHOT.jar --shared |
| 125 | + |
| 126 | +``` |
| 127 | + |
| 128 | +### Invariants |
| 129 | + |
| 130 | +1. Every image build only creates one layer. |
| 131 | + |
| 132 | +2. The image build command used to create the application layer must work without `--layer-use` and create a standalone image. |
| 133 | + The standalone command must completely specify the module/classpath and all other necessary configuration options |
| 134 | + |
| 135 | +3. The layer specified by `--layer-use` must be compatible with the standalone command line. |
| 136 | + The compatibility rules refer to: |
| 137 | + - class/jar file compatibility (`-cp`, `-p`, same JDK, same GraalVM, same libs, etc.) |
| 138 | + - config compatibility: GC config, etc. |
| 139 | + - Java system properties and Environment variables compatibility |
| 140 | + - access compatibility: no additional unsafe and field accesses are allowed |
| 141 | + |
| 142 | + In case of incompatibility an error message is printed and the build process is aborted. |
| 143 | + |
| 144 | +### Limitations |
| 145 | + |
| 146 | +- Layers are platform dependent. A layer created with `--layer-create` on a specific OS/architecture |
| 147 | + cannot be loaded by `--layer-use` on a different OS/architecture. |
| 148 | +- Each layer can only depend on a previous layer. We explicitly make it impossible to depend on more than one layer to |
| 149 | + avoid any potential issues that can stem from _multiple inheritance_. |
| 150 | +- A shared layer is using the _.so_ extension to conform with the standard OS loader restrictions. However, it is not a |
| 151 | + standard shared library file, and it cannot be used with other applications. |
| 152 | + |
| 153 | +## Packaging Native Image Layers |
| 154 | + |
| 155 | +At build time a shared layer is stored in a layer archive that contains the following artifacts: |
| 156 | + |
| 157 | +```shell |
| 158 | +[shared-layer.nil] # shared layer archive file |
| 159 | + ├── shared-layer.json # snapshot of the shared layer metadata; used by subsequent build processes |
| 160 | + ├── shared-layer.so # shared object of the shared layer; used by subsequent build processes and at run time |
| 161 | + └── shared-layer.properties # contains info about layer input data |
| 162 | +``` |
| 163 | + |
| 164 | +The layer snapshot file will be consumed by subsequent build processes that depend on this layer. |
| 165 | +It contains Native Image metadata, such as the analysis universe and available image singletons. |
| 166 | +The shared object file will be used at build time for symbol resolution, and at run time for application execution. |
| 167 | +The layer properties file contains metadata that uniquely identifies this layer: the options used to create the |
| 168 | +layer, all the input files and their checksum. |
| 169 | +Subsequent layer builds use the properties file to validate the layers they depend on: the JAR files that the build |
| 170 | +depends on must exactly match those that were used to build the previous layers. |
0 commit comments