Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Oracle GraalVM #144

Merged
merged 5 commits into from
Dec 7, 2023
Merged

Add Oracle GraalVM #144

merged 5 commits into from
Dec 7, 2023

Conversation

dmikusa
Copy link
Contributor

@dmikusa dmikusa commented Aug 8, 2023

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 paketo-buildpacks/rfcs#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

  • I have viewed, signed, and submitted the Contributor License Agreement.
  • I have linked issue(s) that this PR should close using keywords or the Github UI (See docs)
  • I have added an integration test, if necessary.
  • I have reviewed the styleguide for guidance on my code quality.
  • I'm happy with the commit history on this PR (I have rebased/squashed as needed).

@dmikusa dmikusa added semver:minor A change requiring a minor version bump type:enhancement A general enhancement labels Aug 8, 2023
@dmikusa dmikusa requested a review from a team as a code owner August 8, 2023 04:02
@dmikusa dmikusa added the note:on-hold We can't start working on this issue yet label Aug 8, 2023
@dmikusa
Copy link
Contributor Author

dmikusa commented Aug 8, 2023

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
Copy link
Contributor

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?

buildpack.toml Outdated Show resolved Hide resolved
@dmikusa
Copy link
Contributor Author

dmikusa commented Sep 6, 2023

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
Copy link
Contributor

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

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

@mjhaugsdal
Copy link

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

@dmikusa
Copy link
Contributor Author

dmikusa commented Oct 4, 2023

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
Copy link

schrepfler commented Nov 24, 2023

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
Copy link
Contributor Author

dmikusa commented Nov 27, 2023

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.

dmikusa and others added 3 commits December 5, 2023 15:08
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.

Signed-off-by: Daniel Mikusa <dan@mikusa.com>
Signed-off-by: Daniel Mikusa <dan@mikusa.com>
@anthonydahanne
Copy link
Member

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
Copy link
Member

anthonydahanne commented Dec 5, 2023

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: #144 (comment) and #144 (comment)

@anthonydahanne
Copy link
Member

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
Copy link
Contributor

@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
Copy link
Contributor

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?

- Adds a note to the license section to remind users it is their responsibility to read, understand, and comply with licenses for the software being installed
- Updates the behavior section
- Updates the buildpack.toml description

Signed-off-by: Daniel Mikusa <dan@mikusa.com>
@dmikusa
Copy link
Contributor Author

dmikusa commented Dec 6, 2023

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
Copy link
Member

@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
Copy link

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
Copy link
Member

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

  • GraalVM 17 Native Build:
    pack build apps/native --env BP_MAVEN_ACTIVE_PROFILES=native -b docker.io/anthonydahanne/oracle:4.0.0-anthony -b urn:cnb:builder:paketo-buildpacks/java-native-image -B paketobuildpacks/builder-jammy-tiny:latest

  • GraalVM 21 Native Build:

        <parent>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
-               <version>3.1.0</version>
+               <version>3.2.0</version>
                <relativePath /> <!-- lookup parent from repository -->
        </parent>
        <groupId>io.paketo</groupId>
@@ -14,7 +14,7 @@
        <description>Demo project for Spring Boot</description>

        <properties>
-               <java.version>17</java.version>
+               <java.version>21</java.version>
        </properties>

pack build apps/native --env BP_JVM_VERSION=21 --env BP_MAVEN_ACTIVE_PROFILES=native -b docker.io/anthonydahanne/oracle:4.0.0-anthony -b urn:cnb:builder:paketo-buildpacks/java-native-image -B paketobuildpacks/builder-jammy-tiny:latest

Copy link
Contributor

@fniephaus fniephaus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for putting this together. I only have a minor comment about a wording issue.

README.md Outdated Show resolved Hide resolved
@schrepfler
Copy link

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

Co-authored-by: Fabio Niephaus <code@fniephaus.com>
@dmikusa
Copy link
Contributor Author

dmikusa commented Dec 6, 2023

@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
Copy link
Contributor Author

dmikusa commented Dec 6, 2023

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

@anthonydahanne anthonydahanne merged commit 6c58f30 into main Dec 7, 2023
5 checks passed
@anthonydahanne anthonydahanne deleted the oracle-native branch December 7, 2023 14:53
@dmikusa dmikusa removed the note:on-hold We can't start working on this issue yet label Dec 7, 2023
@schrepfler
Copy link

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
Copy link
Contributor Author

dmikusa commented May 13, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver:minor A change requiring a minor version bump type:enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants