paketo-buildpacks / spring-boot

A Cloud Native Buildpack that contributes Spring Boot dependency information and slices an application into multiple layers
Apache License 2.0
164 stars 21 forks source link

Remove 'org.springframework.boot.loader.nio.file.NestedFileSystemProvider' for Spring Boot 3.2+ native image Applications #488

Closed anthonydahanne closed 3 weeks ago

anthonydahanne commented 3 weeks ago

this is a copy of https://github.com/paketo-buildpacks/native-image/issues/321

I believe it's more appropriate to handle this issue from spring-boot code base

Issue

As explained on StackOverflow, or also in the original issue on Github, the user could be unable to create a Spring Boot 3.2+ native application with such an error during GraalVM native-image step 2/8 :

[INFO]     [creator]     Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: An object of type 'org.springframework.boot.loader.nio.file.NestedFileSystemProvider' was found in the image heap. This type, however, is marked for initialization at image run time for the following reason: classes are initialized at run time by default.
[INFO]     [creator]     This is not allowed for correctness reasons: All objects that are stored in the image heap must be initialized at build time.
[INFO]     [creator]     
[INFO]     [creator]     You now have two options to resolve this:
[INFO]     [creator]     
[INFO]     [creator]     1) If it is intended that objects of type 'org.springframework.boot.loader.nio.file.NestedFileSystemProvider' are persisted in the image heap, add 
[INFO]     [creator]     
[INFO]     [creator]         '--initialize-at-build-time=org.springframework.boot.loader.nio.file.NestedFileSystemProvider'
[INFO]     [creator]     
[INFO]     [creator]     to the native-image arguments. Note that initializing new types can store additional objects to the heap. It is advised to check the static fields of 'org.springframework.boot.loader.nio.file.NestedFileSystemProvider' to see if they are safe for build-time initialization,  and that they do not contain any sensitive data that should not become part of the image.
[INFO]     [creator]     
[INFO]     [creator]     2) If these objects should not be stored in the image heap, you can use 
[INFO]     [creator]     
[INFO]     [creator]         '--trace-object-instantiation=org.springframework.boot.loader.nio.file.NestedFileSystemProvider'
[INFO]     [creator]     
[INFO]     [creator]     to find classes that instantiate these objects. Once you found such a class, you can mark it explicitly for run time initialization with 
[INFO]     [creator]     
[INFO]     [creator]         '--initialize-at-run-time=<culprit>'
[INFO]     [creator]     
[INFO]     [creator]     to prevent the instantiation of the object.
[INFO]     [creator]     
[INFO]     [creator]     If you are seeing this message after upgrading to a new GraalVM release, this means that some objects ended up in the image heap without their type being marked with --initialize-at-build-time.
[INFO]     [creator]     To fix this, include '--initialize-at-build-time=org.springframework.boot.loader.nio.file.NestedFileSystemProvider' in your configuration. If the classes do not originate from your code, it is advised to update all library or framework dependencies to the latest version before addressing this error.
[INFO]     [creator]     
[INFO]     [creator]     The following detailed trace displays from which field in the code the object was reached.
[INFO]     [creator]     Object was reached by
[INFO]     [creator]       manually created constant
[INFO]     [creator]     --------------------------------------------------------------------------------
[INFO]     [creator]         6.1s (9.6% of total time) in 130 GCs | Peak RSS: 1.21GB | CPU load: 6.54
[INFO]     [creator]     ================================================================================
[INFO]     [creator]     Failed generating 'com.example.demo.DemoApplication' after 1m 1s.
[INFO]     [creator]     unable to invoke layer creator
[INFO]     [creator]     unable to contribute native-image layer
[INFO]     [creator]     error running build
[INFO]     [creator]     exit status 1
[INFO]     [creator]     ERROR: failed to build: exit status 1

Workaround

As @scottfrederick suggested, just set this environment variable for native-image buildpack to pick up.

Maven:

<BP_NATIVE_IMAGE_BUILD_ARGUMENTS>-H:-AddAllFileSystemProviders</BP_NATIVE_IMAGE_BUILD_ARGUMENTS>

Using Pack CLI

--env BP_NATIVE_IMAGE_BUILD_ARGUMENTS="-H:-AddAllFileSystemProviders"

Suggested Solution

When spring-boot buildpack has detected the user wanted a native-image, from an application using SB 3.2+, remove the line containing "org.springframework.boot.loader.nio.file.NestedFileSystemProvider" from the file named "META-INF/services/java.nio.file.spi.FileSystemProvider" - if it's the only line of the file, remove the whole file

KafkaProServerless commented 3 weeks ago

Thank you