paketo-buildpacks / oracle

A Cloud Native Buildpack that provides the Oracle JDK implementations of JREs and JDKs
Apache License 2.0
1 stars 3 forks source link

Add Oracle GraalVM #144

Closed dmikusa closed 11 months ago

dmikusa commented 1 year ago

Summary

This PR adds Oracle GraalVM support to the Oracle buildpack. This allows you to use Oracle GraalVM to build your native-image applications. Presently, it does not allow you to build JVM based applications with GraalVM. Instead, it will use the Oracle JDK for this.

Use Cases

This is a short spike on how we could possibly implement https://github.com/paketo-buildpacks/rfcs/pull/294. The benefit of this approach is the simplicity and low amount of work it requires to get users to build native-image apps with Oracle GraalVM.

It does have the drawback mentioned in the commit message where you cannot at the moment select Oracle GraalVM to build JVM-based apps. It will continue to use Oracle JDK for that.

Checklist

dmikusa commented 1 year ago

If you want to try this, I have a demo image available at docker.io/dmikusa/paketo-buildpacks-oracle.

Ex:

pack build apps/native -p target/demo-0.0.1-SNAPSHOT.jar -e BP_NATIVE_IMAGE=true -e BP_JVM_VERSION=17 -b docker.io/dmikusa/paketo-buildpacks-oracle -b urn:cnb:builder:paketo-buildpacks/java-native-image -B paketobuildpacks/builder-jammy-tiny:latest
fniephaus commented 1 year ago

First of all, thanks a lot for putting this PR together, @dmikusa! I'll go over it next week and probably come back with a couple of questions. I just tried to see whether I can use this to build a simple Spring app, but unfortunately, the build fails with the following error:

[INFO]     [creator]     ======== Error: paketo-buildpacks/oracle@v3.9.4-10-gbd38a6c ========
[INFO]     [creator]     fork/exec /cnb/buildpacks/paketo-buildpacks_oracle/v3.9.4-10-gbd38a6c/bin/detect: exec format error

Not sure if this is me doing something wrong or a problem in your version of the oracle buildpack?

dmikusa commented 1 year ago

Not sure if this is me doing something wrong or a problem in your version of the oracle buildpack?

🤦 No, that's cause I'm on an M1 Mac. I need to rebuild it on an AMD64 machine.

I've updated the image, give it another pull and try again. It should work now.

fniephaus commented 1 year ago

I've updated the image, give it another pull and try again. It should work now.

It does! Thanks a lot, @dmikusa! :)

mjhaugsdal commented 1 year ago

Will this be updated with new JDK 21 which has been released in the meantime?

dmikusa commented 1 year ago

The demo image isn't going to be updated. That's just a proof of concept for the RFC.

I'm hopeful that we can get the RFC approved soon though and get all of this merged into the actual buildpack. When that happens, yes we'll absolutely be including Java 21 support.

schrepfler commented 1 year ago

I notice the PR discusses native-image, am I correct in understanding the same can't be used with as vanilla graalvm sdk? This might be good time to push for that support as spring 3.2 and java 21 are out so people will be looking at graalvm support with the free license.

dmikusa commented 12 months ago

FYI, we have the RFC basically approved but are waiting on legal clearance because this is a new license. It's taking a while, but we have to follow the CFF's rules in this regard. As soon as we get clearance, I'm going to update and get this merged.

anthonydahanne commented 11 months ago

Hello @dmikusa , I took the liberty to update your PR (rebase on main, that included Java 21 in favor of Java 20) Let me see if I can add the explicit warnings "YOU ACCEPTED THE LICENSE ..."

anthonydahanne commented 11 months ago

hum; I've republished my oracle-buildpack to : docker.io/anthonydahanne/oracle:4.0.0-anthony but unfortunately, I can't build a native app; always stuck with:

[builder] [1/8] Initializing...                                            (4.7s @ 0.21GB)
[builder]  Java version: 21.0.1+12, vendor version: Oracle GraalVM 21.0.1+12.1
[builder]  Graal compiler: optimization level: 2, target machine: x86-64-v3, PGO: ML-inferred
[builder]  C compiler: gcc (linux, x86_64, 11.4.0)
[builder]  Garbage collector: Serial GC (max heap size: 80% of RAM)
[builder]  2 user-specific feature(s):
[builder]  - com.oracle.svm.thirdparty.gson.GsonFeature
[builder]  - org.springframework.aot.nativex.feature.PreComputeFieldFeature
[builder] --------------------------------------------------------------------------------
[builder]  3 experimental option(s) unlocked:
[builder]  - '-H:Name' (alternative API option(s): -o io.paketo.demo.DemoApplication; origin(s): command line)
[builder]  - '-H:+StaticExecutableWithDynamicLibC' (origin(s): command line)
[builder]  - '-H:ReflectionConfigurationResources' (origin(s): 'META-INF/native-image/io.netty/netty-transport/native-image.properties' in 'file:///workspace/BOOT-INF/lib/netty-transport-4.1.101.Final.jar')
[builder] --------------------------------------------------------------------------------
[builder] Build resources:
[builder]  - 23.59GB of memory (75.3% of 31.33GB system memory, determined at start)
[builder]  - 8 thread(s) (100.0% of 8 available processor(s), determined at start)
[builder] SLF4J: No SLF4J providers were found.
[builder] SLF4J: Defaulting to no-operation (NOP) logger implementation
[builder] SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
[builder] [2/8] Performing analysis...  []                                (23.8s @ 0.74GB)
[builder]     9,465 reachable types   (83.0% of   11,398 total)
[builder]    12,763 reachable fields  (57.1% of   22,336 total)
[builder]    47,333 reachable methods (56.9% of   83,239 total)
[builder]     2,993 types,   316 fields, and 2,091 methods registered for reflection
[builder]
[builder] Error: Classes that should be initialized at run time got initialized during image building:
[builder]  ch.qos.logback.classic.Logger was unintentionally initialized at build time. To see why ch.qos.logback.classic.Logger got initialized use --trace-class-initialization=ch.qos.logback.classic.Logger
[builder] ch.qos.logback.core.status.InfoStatus was unintentionally initialized at build time. To see why ch.qos.logback.core.status.InfoStatus got initialized use --trace-class-initialization=ch.qos.logback.core.status.InfoStatus
[builder] ch.qos.logback.core.status.StatusBase was unintentionally initialized at build time. To see why ch.qos.logback.core.status.StatusBase got initialized use --trace-class-initialization=ch.qos.logback.core.status.StatusBase
[builder] ch.qos.logback.classic.Level was unintentionally initialized at build time. To see why ch.qos.logback.classic.Level got initialized use --trace-class-initialization=ch.qos.logback.classic.Level
[builder] org.slf4j.LoggerFactory was unintentionally initialized at build time. To see why org.slf4j.LoggerFactory got initialized use --trace-class-initialization=org.slf4j.LoggerFactory
[builder] ch.qos.logback.core.util.Loader was unintentionally initialized at build time. To see why ch.qos.logback.core.util.Loader got initialized use --trace-class-initialization=ch.qos.logback.core.util.Loader
[builder] ch.qos.logback.core.util.StatusPrinter was unintentionally initialized at build time. To see why ch.qos.logback.core.util.StatusPrinter got initialized use --trace-class-initialization=ch.qos.logback.core.util.StatusPrinter
[builder] To see how the classes got initialized, use --trace-class-initialization=ch.qos.logback.classic.Logger,ch.qos.logback.core.status.InfoStatus,ch.qos.logback.core.status.StatusBase,ch.qos.logback.classic.Level,org.slf4j.LoggerFactory,ch.qos.logback.core.util.Loader,ch.qos.logback.core.util.StatusPrinter
[builder] --------------------------------------------------------------------------------
[builder]     2.8s (9.6% of total time) in 154 GCs | Peak RSS: 1.51GB | CPU load: 6.79
[builder] ================================================================================
[builder] Finished generating 'io.paketo.demo.DemoApplication' in 28.7s.
[builder] unable to invoke layer creator
[builder] unable to contribute native-image layer
[builder] error running build
[builder] exit status 1
[builder] ERROR: failed to build: exit status 1
ERROR: failed to build: executing lifecycle: failed with status code: 51

~~Tell me if you're luckier than me @dmikusa ... I run this from an Ubuntu x86_64 with: pack build apps/native -e BP_NATIVE_IMAGE=true -e BP_JVM_VERSION=21 -b docker.io/anthonydahanne/oracle:4.0.0-anthony -b urn:cnb:builder:paketo-buildpacks/java-native-image -B paketobuildpacks/builder-jammy-tiny:latest on /samples/java/native-image/spring-boot-native-image-maven~~

Solved, works fine, see: https://github.com/paketo-buildpacks/oracle/pull/144#issuecomment-1843051019 and https://github.com/paketo-buildpacks/oracle/pull/144#issuecomment-1842687862

anthonydahanne commented 11 months ago

Also, wrt to explicit messaging about Oracle license, I suggest we insert the messaging both in README.md like you told me earlier @dmikusa as well as in the logs:

Screenshot 2023-12-05 at 16 48 06 Screenshot 2023-12-05 at 16 50 22
fniephaus commented 11 months ago

@anthonydahanne the Spring app you're trying to build uses 3.1.X. Don't you need 3.2.x for Java 21 support?

fniephaus commented 11 months ago

Regarding the license notice, I thought the default bellsoft/liberica buildpack already has a similar one that can be adapted? It probably needs to mention the Liberica NIK EULA somewhere, no?

dmikusa commented 11 months ago

I pushed an update to the README to clarify the behavior now includes Native Image support. Also, I added a small blurb to the license section at the bottom. @fniephaus and @anthonydahanne let me know what you think about that. I'm not tied to the wording, I just want to make it clear the buildpack is just an installer and you as a user are responsible for ensuring compliance with all license requirements.

anthonydahanne commented 11 months ago

@fniephaus I also thought of Spring Boot 3.2, and got the same result; probably something I missed with instrumentation of classes, I'll have a deeper look tomorrow

@dmikusa thank you for updating the README.md , looks good!

mjhaugsdal commented 11 months ago

I ran successfully with Spring Boot 3.2 using spring-boot-maven-plugin + native-maven-plugin. The bindings and proxy are due to building behind corporate proxy. Here is my plugin setup:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <image>
            <network>host</network>
            <builder>paketobuildpacks/builder-jammy-tiny:latest</builder>
            <buildpacks>
                <buildpack>docker.io/anthonydahanne/oracle:4.0.0-anthony</buildpack>
                <buildpack>urn:cnb:builder:paketo-buildpacks/java-native-image</buildpack>
            </buildpacks>
            <env>
                <BP_JVM_VERSION>21</BP_JVM_VERSION>
                <HTTP_PROXY>${docker.http.proxy}</HTTP_PROXY>
                <HTTPS_PROXY>${docker.https.proxy}</HTTPS_PROXY>
                <NO_PROXY>${docker.noProxy}</NO_PROXY>
            </env>
            <bindings>
                <binding>
                    ${project.build.directory}/platform/bindings/certificates:/platform/bindings/certificates
                </binding>
            </bindings>
        </image>
    </configuration>
</plugin>
<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
</plugin>

image

anthonydahanne commented 11 months ago

Thank you @mjhaugsdal ! You validated it works from the Spring Boot Maven Plugin. This morning, I got my ideas clearer and validated it works from the pack CLI as well: From https://github.com/paketo-buildpacks/samples/tree/main/java/native-image/spring-boot-native-image-maven

schrepfler commented 11 months ago

Would it work with spring maven plugin and packaging the container with the GraalVM JDK but without the native part?

dmikusa commented 11 months ago

@schrepfler Presently, no. If you were to install a JVM, it would give you Oracle's free JDK, not Oracle GraalVM JDK. Presently, this is only going to use Oracle GraalVM for building native-image.

We are aware that folks are interested in the use case you mentioned, using Oracle GraalVM as a JVM. It's on the roadmap to support but requires more work. We wanted to get this out for folks to use in the meantime.

dmikusa commented 11 months ago

Tested some builds from source/precompiled-jar, with Java 17 and 21. Looks good to me.

schrepfler commented 6 months ago

Any updates on this, we'd like to give it a try as we've seen good performance improvement locally but as we strictly use springboot with the maven plugin and delegate to paketo we don't want to go outside of it's build ecosystem.

dmikusa commented 6 months ago

@schrepfler please follow paketo-buildpacks/libjvm#431 for updates.