{"id":15805065,"url":"https://github.com/ddobrin/native-spring-cloud-run-with-graalvm","last_synced_at":"2025-03-31T22:09:17.445Z","repository":{"id":134175883,"uuid":"427470489","full_name":"ddobrin/native-spring-cloud-run-with-graalvm","owner":"ddobrin","description":"A simple example of a Function deployed in Cloud Run, available as JVM or Native Image","archived":false,"fork":false,"pushed_at":"2022-12-13T21:20:56.000Z","size":95,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-06T02:04:04.392Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ddobrin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-12T19:12:50.000Z","updated_at":"2022-08-15T16:50:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"c3d8abbc-2a2b-4e19-9a15-85fb5d3e2f59","html_url":"https://github.com/ddobrin/native-spring-cloud-run-with-graalvm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ddobrin%2Fnative-spring-cloud-run-with-graalvm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ddobrin%2Fnative-spring-cloud-run-with-graalvm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ddobrin%2Fnative-spring-cloud-run-with-graalvm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ddobrin%2Fnative-spring-cloud-run-with-graalvm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ddobrin","download_url":"https://codeload.github.com/ddobrin/native-spring-cloud-run-with-graalvm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246547366,"owners_count":20794970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-05T02:03:33.913Z","updated_at":"2025-03-31T22:09:17.403Z","avatar_url":"https://github.com/ddobrin.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"### [Last updated: August 1, 2022]\n------\n**Learn how to build JVM and Native Java images with Spring Native and GraalVM, then deploy them on the Google CloudRun serverless compute platform.**\n\n\nThe sample app provides a simple `Hello` web app based on Spring Boot and Spring Cloud Functions. \nThe focus is on building and deploying native images to a serverless platform. The update to this repo follows the latest release of GraalVM 22.2.0 with Java 17 support, which brings a series of significant improvements.\n\nIntel and Apple Silicon builds are supported for the different build methods at this time.\n[GraalVM 22.2: Smaller JDK size, improved memory usage, better library support, and more!](https://medium.com/graalvm/graalvm-22-2-smaller-jdk-size-improved-memory-usage-better-library-support-and-more-cb34b5b68ec0)\n\n[Full details - GraalVM 22.1: Developer experience improvements, Apple Silicon builds, and more](https://medium.com/graalvm/graalvm-22-1-developer-experience-improvements-apple-silicon-builds-and-more-b7ac9a0f6066)\n\n### `Dive into`\n1. Build \n    * JVM \u0026 Native `Application image` with the Spring Boot Maven plugin and GraalVM\n    * JVM \u0026 Native `Docker image` using Java/Native Java Paketo Buildpacks and Compression\n2. Generate \n   * Native Tests\n3. Deploy\n    * Deploy to Google Cloud Run\n4. Develop\n   * How to use the new Quick Build Mode for Developers!\n5. Analyze \n   * App \u0026 Container image sizes  \n   * Start-up latency\n   * RSS memory consumption\n\n### `Java and library versions in use`\n* Spring Boot 2.7.2\n* Spring Native 0.12.1 \n* Native Buildtools 0.9.13\n* Spring Cloud 2021.0.3\n* OpenJDK\n  * openjdk version \"17.0.4\" 2022-07-19\n* GraalVM CE\n  * OpenJDK Runtime Environment GraalVM CE 22.2.0 (build 17.0.4+8-jvmci-22.2-b06)\n  * OpenJDK 64-Bit Server VM GraalVM CE 22.2.0 (build 17.0.4+8-jvmci-22.2-b06, mixed mode, sharing)\n* Java compatibility level: Java 17\n\n### `Known Issues`\n* Java Native Buildpacks are failing on M1 Macs as of today; Native Java App executables can be built cleanly though\n* UPX compression for M1 Macs is a known issue with a pending patch\n\n# Installation\nInstall GraalVM from:\n* [from GraalVM Github repo](https://github.com/graalvm/graalvm-ce-builds/releases)\n* [using Homebrew](https://github.com/graalvm/homebrew-tap)\n* [SDKMan](https://sdkman.io/): `sdk install java 22.2.0.r17-grl`\n\nInstall the native-image builder before building native executables: \n```shell\ngu install native-image\n```\n\n# Build\n\n## Build application images\nBuilding an executable application with the GraalVM compiler requires the installation of the GraalVM and the native-image builder utility and leverages the following `Maven profile`:\n* `jvm` (or noprofile specified, as default)\n* `native`\n\n### Build code as a JVM app using the Spring Boot Maven plugin\n```bash \n# build and run code using\n./mvnw clean package spring-boot:run\n\n# test locally from a terminal window\ncurl -w'\\n' -H 'Content-Type: text/plain' localhost:8080 -d \"from a JVM app\"\n```\n### Build code as a Native Java app using the GraalVM compiler\n```bash \n# switch to the GraalVM JDK for this build\n# ex, when using SDKman, validate that you use the GraaLVM compiler\nsdk use java 22.2.0.r17-grl\n\n# build and run code using GraalVM\n# generating native tests is skipped for reduced build latency\n./mvnw clean package -Pnative -DskipTests\n\n# start the native executable\n./target/hello-function\n\n# test locally from a terminal window\ncurl -w'\\n' -H 'Content-Type: text/plain' localhost:8080 -d \"from a Native app\"\n```\n## Build Docker images\n\nBuilding the code with the Spring Boot Maven wrapper uses the following `Maven profiles`:\n* `native-image` - build a Native image leveraging GraalVM\n* `jvm-image` - build a JVM-based image leveraging OpenJDK\n\n### Build code as a JVM Docker image using the Spring Boot Maven plugin and Java Paketo Buildpacks\n```bash \n# build image with default configuration\n./mvnw clean spring-boot:build-image\n\n# build image with the CNB Paketo buildpack of your choice\n./mvnw clean spring-boot:build-image -Pjvm-image \n\n# start Docker image\ndocker run -p 8080:8080 hello-function-jvm:r17\n\n# test Docker image locally\ncurl -w'\\n' -H 'Content-Type: text/plain' localhost:8080 -d \"from a JVM app running in a container\"\n```\n\n### Build code as a Spring Native Docker image using the Spring Boot Maven plugin and the Java Native Paketo Buildpacks\n```bash \n# build image with the CNB Paketo buildpack of your choice\n# generating native tests is skipped for reduced build latency\n./mvnw clean spring-boot:build-image -Pnative-image -DskipTests\n\n# start Docker image\ndocker run -p 8080:8080 hello-function-native:r17\n\n# test Docker image locally\ncurl -w'\\n' -H 'Content-Type: text/plain' localhost:8080 -d \"from a Native app running in a container\"\n```\n\n# Generate Native Tests\nTesting Java code with JUnit 5 behaves exactly the same in native execution as with the JVM. \nWriting proper unit tests and generating native test images assists you in ensuring that the native image of the app will work in the same manner as on the JVM\n\nThe [Native Build Tools](https://graalvm.github.io/native-build-tools/latest/index.html) project provides plugins for different build tools to add support for building and testing native applications written in Java (or any other language compiled to JVM bytecode).\n\nTo build native tests\n```bash \n# switch to the GraalVM JDK for this build\n# ex, when using SDKman, validate that you use the GraaLVM compiler\nsdk use java 22.2.0.r17-grl\n\n# test the app with native tests\n./mvnw -Pnative test\n\n# start the native test executable\n$ ./target/native-tests\n```\n\nObserve the significant latency reduction in test execution:\n```text\nJUnit JVM tests\n...\n2022-08-01 12:05:48.527  INFO 78674 --- [           main] e.h.SpringNativeFunctionApplicationTests : Started SpringNativeFunctionApplicationTests in 0.812 seconds (JVM running for 1.665)\n...\n```\n\nNative Tests\n```text\n12:12:24.087 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: []\ncom.example.hello.SpringNativeFunctionApplicationTests \u003e contextLoads() SUCCESSFUL\n\nTest run finished after 59 ms\n[         2 containers found      ]\n[         0 containers skipped    ]\n[         2 containers started    ]\n[         0 containers aborted    ]\n[         2 containers successful ]\n[         0 containers failed     ]\n[         1 tests found           ]\n[         0 tests skipped         ]\n[         1 tests started         ]\n[         0 tests aborted         ]\n[         1 tests successful      ]\n[         0 tests failed          ]\n```\n# Deploy\n\n## Cloud Run Deploy\n\nBuild the image as a JVM or native image and deploy it to Cloud Run from the command-line. You can also deploy directly from the GCP console.\n\n**Note**: Please note the Project ID of the project where you wish to deploy your service\n\n#### Build\n```shell\n# authorize the user to GCP\ngcloud auth list\n\n# check if the project is set\ngcloud config list\n\n...\nproject = optimize-serverless-apps\n...\n\n# set project ID if not already set\ngcloud config set project \u003cproject id\u003e\n# ex:\ngcloud config set project optimize-serverless-apps\n\n# tag the images and push them to the Container Registry \ndocker tag hello-function-jvm:r17 gcr.io/optimize-serverless-apps/hello-function-jvm:r17\ndocker tag hello-function-native:r17-upx gcr.io/optimize-serverless-apps/hello-function-native:r17\n\n# push the image(s) to the Container Registry\ndocker push gcr.io/optimize-serverless-apps/hello-function-jvm:r17\ndocker push gcr.io/optimize-serverless-apps/hello-function-native:r17\n```\n\nAs a developer, the service can be deployed, for testing, unauthorized, while providing full access to the service.\nHowever, developers, in addition to administrative actions such as creating, updating, and deleting services, often want to test services privately before releasing them.\n\nYou have to ensure that you grant permissions to access the services you are authenticating to. \n\nFor development, the easiest way to test a service that requires authentication is to use a tool like curl and pass an auth token in the Authorization header.\nThis is NOT recommended outside of testing, and proper tokens should be generated during deployment.\n\n#### Deploy with unauthenticated users:\n```bash\n# deploy the container to CloudRun\n# Note that we are specifying:\n#    app name - hello-function\n#    region - us-central1\n#    memory allocated for the process - 1Gi\n#    simple apps allow all users, unauthenticated, best practice is to set service accounts up\n\n# deploy a JVM image\ngcloud run deploy hello-function-jvm \\\n  --image=gcr.io/optimize-serverless-apps/hello-function-jvm:r17 \\\n  --region us-central1 \\\n  --memory 1Gi --allow-unauthenticated\n\n...\nDeploying container to Cloud Run service [hello-function-jvm] in project [optimize-serverless-apps] region [us-central1]\n✓ Deploying... Done.                                                                                                                                       \n  ✓ Creating Revision...                                                                                                                                   \n  ✓ Routing traffic...                                                                                                                                     \n  ✓ Setting IAM Policy...                                                                                                                                  \nDone.                                                                                                                                                      \nService [hello-function-jvm] revision [hello-function-jvm-00001-soj] has been deployed and is serving 100 percent of traffic.\n\n# deploy a Native Java image\ngcloud run deploy hello-function-native \\\n  --image=gcr.io/optimize-serverless-apps/hello-function-native:r17 \\\n  --region us-central1 \\\n  --memory 1Gi --allow-unauthenticated  \n\n...\nService [hello-function-native] revision [hello-function-native-00001-xah] has been deployed and is serving 100 percent of traffic.\n...\n\n# check that the project has been successfully deployed \n# retrieve the URL where the app can be accessed and send a request\ngcloud run services list\n   SERVICE                   REGION       URL                                                     LAST DEPLOYED AT\n✔  hello-function-jvm          us-central1   https://hello-function-jvm-...-uc.a.run.app          \u003cemail\u003e  2022-08-01T16:04:13.864504Z\n✔  hello-function-native       us-central1   https://hello-function-native-...-uc.a.run.app       \u003cemail\u003e  2022-08-01T16:02:58.368234Z\n\n# Test the JVM service\ncurl -w'\\n' -H 'Content-Type: text/plain' https://hello-function-jvm-...-uc.a.run.app -d \"from a JVM Image\"\nHello: from a JVM Image, Source: a Spring function !\n\n# Test the Native Java service\ncurl -w'\\n' -H 'Content-Type: text/plain' https://hello-function-native-...-uc.a.run.app -d \"from a Native Image\"\nHello: from a Native Image, Source: a Spring function !\n\n# delete the service \ngcloud run services delete hello-function-jvm --region us-central1\ngcloud run services delete hello-function-native --region us-central1\n```\n\n#### Deploy with authenticated users:\n```shell\n# deploy the container to CloudRun\n# Note that we are specifying:\n#    app name - hello-function\n#    region - us-central1\n#    memory allocated for the process - 1Gi\n#    simple apps allow all users, unauthenticated, best practice is to set service accounts up\n\n# deploy JVM image\ngcloud run deploy hello-function-jvm \\\n  --image=gcr.io/optimize-serverless-apps/hello-function-jvm:r17 \\\n  --region us-central1 \\\n  --memory 1Gi\n\n# do not allow unathenticated users at the prompt\nAllow unauthenticated invocations to [hello-function] (y/N)?  N\n\nDeploying container to Cloud Run service [hello-function-jvm] in project [optimize-serverless-apps] region [us-central1]\n...\nService [hello-function-jvm] revision [hello-function-jvm-00001-vel] has been deployed and is serving 100 percent of traffic.\nService URL: https://hello-function-jvm-...-uc.a.run.app\n\n# deploy Native Java image\ngcloud run deploy hello-function-native \\\n  --image=gcr.io/optimize-serverless-apps/hello-function-jvm:r17 \\\n  --region us-central1 \\\n  --memory 1Gi  \n\n# do not allow unathenticated users at the prompt\nAllow unauthenticated invocations to [hello-function] (y/N)?  N\n\nDeploying container to Cloud Run service [hello-function-native] in project [optimize-serverless-apps] region [us-central1]\n...\nService [hello-function-native] revision [hello-function-native-00001-fad] has been deployed and is serving 100 percent of traffic.\nService URL: https://hello-function-native-...-uc.a.run.app\n\n\n# retrieve the URL where the app can be accessed and send a request\ngcloud run services list\n   SERVICE               REGION       URL                                                         LAST DEPLOYED AT\n✔  hello-function-jvm          us-central1   https://hello-function-jvm-...-uc.a.run.app          \u003cemail\u003e  2022-08-01T16:04:13.864504Z\n✔  hello-function-native       us-central1   https://hello-function-native-...-uc.a.run.app       \u003cemail\u003e  2022-08-01T16:02:58.368234Z\n\n# grant the Cloud Run Invoker role to the developer\n# substitute the developer email\n$ gcloud run services add-iam-policy-binding hello-function \\\n    --member='user:\u003cemail\u003e' \\\n    --role='roles/run.invoker'   \\\n    --region us-central1            \n\nUpdated IAM policy for service [hello-function].\nbindings:\n- members:\n  - user:\u003cemail\u003e\n  role: roles/run.invoker\netag: BwXQv-XczNA=\nversion: 1\n...\n\n# developer can  print an identity token for the specified account to generate a token for development\n# command: gcloud auth print-identity-token \n\n# for convenience, you can create an alias\nalias gcurl='curl --header \"Authorization: Bearer $(gcloud auth print-identity-token)\"'\n\n# you can use the new alias to curl the service\n# invoke the JVM image service\ngcurl -w'\\n' -H 'Content-Type: text/plain' https://hello-function-jvm-...-uc.a.run.app -d \"from a JVM Image\"\nHello: from a JVM Image, Source: a Spring function !\n\n# invoke the Native image service\ngcurl -w'\\n' -H 'Content-Type: text/plain' https://hello-function-native-...-uc.a.run.app -d \"from a Native Image\"\nHello: from a Native Image, Source: a Spring function !\n```\n\n#### Clean-up \n```shell\n# delete the service \ngcloud run services delete hello-function-jvm --region us-central1\ngcloud run services delete hello-function-native --region us-central1\n\n```\n\n# How to use Quick Build Mode for Development\n\nQuick Build mode significantly improves build latency by running the compiler in economy mode, with fewer optimizations, resulting in much faster builds.\n\nThis is a Development feature, not recommended for Production !!!\nIn Production, use the default compilation mode, which provides the best runtime performance and memory efficiency!\n\nTo enable quick build mode, add `-Ob (capital “O”, lower case “b”)` when building with the native-image utility.\nEx.:\n```xml\n\u003cprofile\u003e\n    \u003cid\u003enative\u003c/id\u003e\n    ...\n    \u003cdependencies\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003eorg.graalvm.buildtools\u003c/groupId\u003e\n            \u003cartifactId\u003ejunit-platform-native\u003c/artifactId\u003e\n            \u003cversion\u003e${native-buildtools.version}\u003c/version\u003e\n            \u003cscope\u003etest\u003c/scope\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n    \u003cbuild\u003e\n        \u003cplugins\u003e\n            \u003cplugin\u003e\n                \u003cgroupId\u003eorg.graalvm.buildtools\u003c/groupId\u003e\n                \u003cartifactId\u003enative-maven-plugin\u003c/artifactId\u003e\n                \u003cversion\u003e${native-buildtools.version}\u003c/version\u003e\n                \u003cextensions\u003etrue\u003c/extensions\u003e\n                \u003c!--Enable Quick Build mode --\u003e\n                \u003cconfiguration\u003e\n                    \u003cbuildArgs\u003e-Ob\u003c/buildArgs\u003e\n                \u003c/configuration\u003e\n                \u003c!--end --\u003e\n                ...\n```\n\nWhen building an app, the GraalVM compiler will perform 7 steps,  from initialization to building an app image.\nThe output provides significantly more information than in previous versions.\n\nStep `[6/7] Compiling methods ...` is the step when optimizations will be executed.\n\nExcerpt from building the `optimized, production app`:\n```text\n========================================================================================================================\nGraalVM Native Image: Generating 'hello-function' (executable)...\n========================================================================================================================\n[1/7] Initializing...                                                                                    (7.2s @ 0.19GB)\n Version info: 'GraalVM 22.2.0 Java 17 CE'\n Java version info: '17.0.4+8-jvmci-22.2-b06'\n C compiler: cc (apple, x86_64, 13.1.6)\n Garbage collector: Serial GC\n[2/7] Performing analysis...  [********]                                                                (51.2s @ 1.95GB)\n  14,442 (90.90%) of 15,888 classes reachable\n  22,701 (66.51%) of 34,131 fields reachable\n  68,679 (61.81%) of 111,106 methods reachable\n     786 classes,   281 fields, and 3,805 methods registered for reflection\n      63 classes,    69 fields, and    55 methods registered for JNI access\n       5 native libraries: -framework CoreServices, -framework Foundation, dl, pthread, z\n[3/7] Building universe...                                                                               (7.7s @ 4.66GB)\n[4/7] Parsing methods...      [***]                                                                     (10.0s @ 5.14GB)\n[5/7] Inlining methods...     [***]                                                                      (5.8s @ 3.46GB)\n[6/7] Compiling methods...    [********]                                                                (63.2s @ 3.83GB)\n[7/7] Creating image...                                                                                  (6.8s @ 2.68GB)\n  30.27MB (50.00%) for code area:    45,406 compilation units\n  29.99MB (49.54%) for image heap:  325,057 objects and 292 resources\n 284.67KB ( 0.46%) for other data\n  60.54MB in total\n------------------------------------------------------------------------------------------------------------------------\nTop 10 packages in code area:                               Top 10 object types in image heap:\n   1.66MB sun.security.ssl                                     6.48MB byte[] for code metadata\n   1.05MB java.util                                            3.56MB java.lang.Class\n 732.48KB com.sun.crypto.provider                              3.06MB java.lang.String\n 649.59KB org.apache.tomcat.util.net                           2.91MB byte[] for embedded resources\n 566.29KB java.lang.invoke                                     2.61MB byte[] for java.lang.String\n 551.31KB org.apache.catalina.core                             2.51MB byte[] for general heap data\n 493.46KB org.apache.coyote.http2                              1.21MB com.oracle.svm.core.hub.DynamicHubCompanion\n 487.28KB java.lang                                          805.55KB byte[] for reflection metadata\n 478.34KB java.util.concurrent                               632.21KB java.lang.String[]\n 469.79KB sun.security.x509                                  585.94KB java.util.HashMap$Node\n  22.89MB for 587 more packages                                4.74MB for 2973 more object types\n------------------------------------------------------------------------------------------------------------------------\n                        6.0s (3.7% of total time) in 34 GCs | Peak RSS: 6.06GB | CPU load: 3.86\n------------------------------------------------------------------------------------------------------------------------\nProduced artifacts:\n /Users/ddobrin/work/dan/native-spring-cloud-run-with-graalvm/target/hello-function (executable)\n /Users/ddobrin/work/dan/native-spring-cloud-run-with-graalvm/target/hello-function.build_artifacts.txt (txt)\n========================================================================================================================\n```\n\nWhen building the `developer app`, less optimizations will be performed, thus speeding the build up. The change is more noticable the larger the number of classes in your project is.\n\nExcerpt from building the `developer, non-prod app` - notice the `warning` at the top of this snippet:\n```text\nYou enabled -Ob for this image build. This will configure some optimizations to reduce image build time.\nThis feature should only be used during development and never for deployment.\n...\n========================================================================================================================\nGraalVM Native Image: Generating 'hello-function' (executable)...\n========================================================================================================================\n[1/7] Initializing...                                                                                    (7.6s @ 0.20GB)\n Version info: 'GraalVM 22.2.0 Java 17 CE'\n Java version info: '17.0.4+8-jvmci-22.2-b06'\n C compiler: cc (apple, x86_64, 13.1.6)\n Garbage collector: Serial GC\n[2/7] Performing analysis...  [********]                                                                (40.6s @ 3.08GB)\n  14,442 (90.90%) of 15,888 classes reachable\n  22,701 (66.51%) of 34,131 fields reachable\n  68,679 (61.81%) of 111,106 methods reachable\n     786 classes,   281 fields, and 3,805 methods registered for reflection\n      63 classes,    69 fields, and    55 methods registered for JNI access\n       5 native libraries: -framework CoreServices, -framework Foundation, dl, pthread, z\n[3/7] Building universe...                                                                               (5.2s @ 2.32GB)\n[4/7] Parsing methods...      [***]                                                                      (5.0s @ 2.78GB)\n[5/7] Inlining methods...     [***]                                                                      (3.1s @ 1.19GB)\n[6/7] Compiling methods...    [******]                                                                  (42.0s @ 1.24GB)\n[7/7] Creating image...                                                                                  (8.5s @ 3.50GB)\n  30.93MB (50.06%) for code area:    45,412 compilation units\n  30.57MB (49.47%) for image heap:  325,090 objects and 292 resources\n 293.46KB ( 0.46%) for other data\n  61.79MB in total\n------------------------------------------------------------------------------------------------------------------------\nTop 10 packages in code area:                               Top 10 object types in image heap:\n   1.73MB sun.security.ssl                                     7.06MB byte[] for code metadata\n   1.07MB java.util                                            3.56MB java.lang.Class\n 784.08KB com.sun.crypto.provider                              3.06MB java.lang.String\n 640.49KB org.apache.tomcat.util.net                           2.91MB byte[] for embedded resources\n 597.39KB java.lang.invoke                                     2.61MB byte[] for java.lang.String\n 575.77KB org.apache.catalina.core                             2.51MB byte[] for general heap data\n 501.10KB org.apache.coyote.http2                              1.21MB com.oracle.svm.core.hub.DynamicHubCompanion\n 485.00KB java.lang                                          805.74KB byte[] for reflection metadata\n 478.21KB sun.security.x509                                  632.36KB java.lang.String[]\n 470.01KB java.util.concurrent                               585.94KB java.util.HashMap$Node\n  23.38MB for 587 more packages                                4.74MB for 2974 more object types\n------------------------------------------------------------------------------------------------------------------------\n                        5.4s (4.4% of total time) in 35 GCs | Peak RSS: 6.12GB | CPU load: 3.60\n------------------------------------------------------------------------------------------------------------------------\nProduced artifacts:\n /Users/ddobrin/work/dan/native-spring-cloud-run-with-graalvm/target/hello-function (executable)\n /Users/ddobrin/work/dan/native-spring-cloud-run-with-graalvm/target/hello-function.build_artifacts.txt (txt)\n========================================================================================================================\n```\n\nPlease note the build latency reduction [Prod/Dev]:\n```\nGraalVM 22.2.0 - significant improvement vs 22.1.0\n[6/7] Compiling methods...    [********]                                (63.2s @ 3.83GB)\n[6/7] Compiling methods...    [******]                                  (42.0s @ 1.24GB)\n\nGraalVM 22.1.0\n[6/7] Compiling methods...    [******]                                  (44.8s @ 4.28GB)\n[6/7] Compiling methods...    [*****]                                   (29.0s @ 3.49GB)\n```\n... as well as lower RSS memory usage and lower CPU load\n```\nGraalVM 22.2.0 - significant improvement vs 22.1.0\n6.0s (3.7% of total time) in 34 GCs | Peak RSS: 6.06GB | CPU load: 3.86\n5.4s (4.4% of total time) in 35 GCs | Peak RSS: 6.12GB | CPU load: 3.60\n\nGraalVM 22.1.0\n19.2s (12.3% of total time) in 37 GCs | Peak RSS: 7.29GB | CPU load: 3.82\n18.3s (11.0% of total time) in 33 GCs | Peak RSS: 6.93GB | CPU load: 3.40\n```\n\n# Analyze\n\n## App and Docker container image sizes\n\nWhat can we learn from comparing JVM and native images? This chapter does not intend to go into the details of JVM vs Native, that area is left for another workshop.\nIn here the intention is to compare the numbers for the latest versions of Java LTS, GraalVM and Spring/\n\nNative images are larger, however they are self-contained and do not require a JVM to run:\n```text\n-rw-r--r--   1 ddobrin  primarygroup  20513323  1 Aug 12:19 hello-function-1.0.0-exec.jar\n-rwxr-xr-x   1 ddobrin  primarygroup  63480256  1 Aug 12:22 hello-function\n```\n\nDocker images for JVM based apps are quite large, while native images are significantly smaller, as the Docker container does not require a JRE to run the Java app.\nThe images shown below have been build with the [Paketo Java Buildpack](https://github.com/paketo-buildpacks/java) and the [Paketo Native Java Buildpack](https://github.com/paketo-buildpacks/native-image) respectively, withtou the need to build a Dockerfile.\n```text\nhello-function-native                                                                  r17-no-compression                                                 0bedca53cafb   42 years ago    92.5MB\nhello-function-native                                                                  r17-upx                                                            ea422a1b1e07   42 years ago    41.9MB\nhello-function-jvm                                                                     r17                                                                021a6af1060f   42 years ago    278MB\n```\n\nBy default, Docker images for Native Java apps are not compressed, however you can compress them using `UPX` or `GZEXE`.\nTo compress the image, you must specify the compression method in the Maven profile:\n```xml\n\u003cprofile\u003e\n    \u003cid\u003enative-image\u003c/id\u003e\n    \u003cbuild\u003e\n        \u003cplugins\u003e\n            \u003cplugin\u003e\n                \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n                \u003cartifactId\u003espring-boot-maven-plugin\u003c/artifactId\u003e\n                \u003cconfiguration\u003e\n                    \u003cclassifier\u003e${repackage.classifier}\u003c/classifier\u003e\n                    \u003cimage\u003e\n                        \u003cbuilder\u003epaketobuildpacks/builder:tiny\u003c/builder\u003e\n                        \u003cname\u003e${project.artifactId}-${native-image-type}:${build.version}\u003c/name\u003e\n                        \u003cenv\u003e\n                            \u003cBP_NATIVE_IMAGE\u003e1\u003c/BP_NATIVE_IMAGE\u003e\n                            \u003cBP_JVM_VERSION\u003e17\u003c/BP_JVM_VERSION\u003e\n                            \u003c!-- \u003cnone\u003e is default --\u003e\n                            \u003c!-- upx or gzexe are supported options --\u003e\n                            \u003cBP_BINARY_COMPRESSION_METHOD\u003eupx\u003c/BP_BINARY_COMPRESSION_METHOD\u003e\n                            \u003c!-- end compression --\u003e\n                            \u003cBP_NATIVE_IMAGE_BUILD_ARGUMENTS\u003e\n                                \u003cremoveSpelSupport\u003etrue\u003c/removeSpelSupport\u003e\n                                \u003cremoveYamlSupport\u003etrue\u003c/removeYamlSupport\u003e\n                            \u003c/BP_NATIVE_IMAGE_BUILD_ARGUMENTS\u003e\n                        \u003c/env\u003e\n                    \u003c/image\u003e\n                \u003c/configuration\u003e\n...\n```\n\n## Start-up latency\nJVM applications start-up latency is significantly improved in native images.\n\nJVM based app:\n```shell\njava -jar target/hello-function-1.0.0-exec.jar\n...\n2022-08-01 12:34:52.650  INFO 84442 --- [           main] c.e.h.SpringNativeFunctionApplication    : Started SpringNativeFunctionApplication in 2.047 seconds (JVM running for 2.464)\n...\n```\n\nNative java app:\n```shell\ntarget/hello-function\n...\n2022-08-01 12:35:41.942  INFO 84640 --- [           main] c.e.h.SpringNativeFunctionApplication    : Started SpringNativeFunctionApplication in 0.064 seconds (JVM running for 0.067)\n...\n```\n\n## RSS memory consumption\nRSS memory consumption is significantly lower in Native Java apps\n\nJVM based app:\n```shell\n# memory usage in MB\nps -o pid,rss,command | grep --color hello-function | awk '{$2=int($2/1024)\"M\";}{ print;}'\n\n# before running an HTTP request\n79764 245M /usr/bin/java -jar target/hello-function-1.0.0-exec.jar\n# after running 5 HTTP requests\n79764 271M /usr/bin/java -jar target/hello-function-1.0.0-exec.jar\n```\n\nNative Java app:\n```shell\n# memory usage in MB\nps -o pid,rss,command | grep --color hello-function | awk '{$2=int($2/1024)\"M\";}{ print;}'\n\n# before running an HTTP request\n80061 49M target/hello-function\n\n# after running 5 HTTP requests\n84640 54M ./target/hello-function\n```\n\n## Changelog\n* August 1, 2022: Updated with GraalVM 22.2.0, Java 17, buildtools 0.9.13\n* July 22, 2022: Updated with GraalVM 22.1.0, Java 17, Spring Boot 2.7.2. buildtools 0.9.11\n* April 30, 2022: Updated with GraalVM 22.1.0, Java 17, Spring Boot 2.6.6\n* May 2, 2022: Deploy to Cloud Run, analysis\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fddobrin%2Fnative-spring-cloud-run-with-graalvm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fddobrin%2Fnative-spring-cloud-run-with-graalvm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fddobrin%2Fnative-spring-cloud-run-with-graalvm/lists"}