Quarkus’ Fast-JAR packaging
In this article we will focus on a specific packaging mode brought by Quarkus: the Fast-JAR. Its main goal is to provide an optimized way of building cloud-ready Java apps.
But first, let’s give a bit of context.
Quarkus is officialy presented as:
Quarkus is a Cloud Native, (Linux) Container First framework for writing Java applications.
In particular, they insist on these two points:
Container First
Minimal footprint Java applications optimal for running in containers.
Microservice First
Brings lightning fast startup time and code turnaround to Java apps.
In order to achieve the two highlighted goals, Minimal footprint and Fast startup time, one of the special Quarkus’ weapons is the Fast-JAR packaging.
Let’s first have a look at the common options available for a Quarkus App packaging as a JAR:
- Uber JAR
- Fast JAR
Note: Another very interesting packaging mode is the binary “Native image”. But it would require another article ;)
Beside the well-known Uber-JAR (alias Fat-JAR which is a JAR that embeds the app classes and a fully functional server runtime) there is the new Fast-JAR option! What it’s all about?
Well, let’s discover…
The Fast-JAR packaging has been introduced in v1.5 as an evolution to the previous default one (now called Legacy-JAR and being deprecated). The main goal is to bring faster startup times and an optimized format for containerized Apps.
How? With two main ideas:
- Splitting the App and it’s dependencies into several folders.
- Pre-computing (at build time) the App’s Classpath.
Let’s develop this two concepts and understand why they help answer the mentioned concerns.
1. Splitting files into folders instead of the usual single JAR archive
After the first build of the image, having the App’s code and dependencies in separate locations reduces the number of image layers that have to be re-created when re-building a container image.
By smartly using several “COPY” instructions in your Dockerfile, you can leverage this optimization by having the last image’s layer containing only your App’s code and the previous layers it’s dependencies.
In turn, re-building an image will take less time when only the App’s code is changed (and not the dependencies)!
2. Pre-computing the Classpath
The Fast-JAR packaging results in creating an artifact that starts faster and consumes less memory than a classic Uber-JAR because it has pre-computed indexed information about which dependency JARs contain classes and resources.
The JVM can thus avoid scanning potentially every JARs on the Classpath as the Uber-JAR case could necessitate.
The App will also fast-boot thanks to a minimal Manifest.mf (located inside the runner-jar). At runtime, the ClassPathLoader will lookup into the pre-generated quarkus-app/quarkus-app-dependencies.txt file instead of scanning the file-system for classes/resources.
3. How to package a Fast-JAR
Building
With Maven command-line:
$ mvn package -Dquarkus.package.type=fast-jar
Or with this setting in application.properties
:
quarkus.package.type=fast-jar
Or using a Maven profile that you will use during the package
goal:
<profile>
<id>staging</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<quarkus.package.type>fast-jar</quarkus.package.type>
</properties>
</profile>
You will then obtain a fast-jar
folder:
./target/quarkus-app/*
Deployment
You must deploy the whole quarkus-app/
folder to your target environment (server or container image).
Then, you can start the App with:
java -jar ./quarkus-app/quarkus-run.jar
Output example:
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-05-11 12:01:58,895 INFO [io.quarkus] (main) getting-started 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.0.3.Final) started in 2.565s. Listening on: http://0.0.0.0:8080
2023-05-11 12:01:58,938 INFO [io.quarkus] (main) Profile prod activated.
2023-05-11 12:01:58,938 INFO [io.quarkus] (main) Installed features: [cdi, resteasy-reactive, smallrye-context-propagation, vertx]
Conclusion
At the time of writing this article, there are not that many resources presenting how the Fast-JAR packaging mode works and why it is relevant. I hope to have contributed addressing this issue with this modest contribution.
Quarkus at its heart aims to make a fact of the past the saying “Java is not a good fit for Cloud environment”. Along with other frameworks like Spring or Micronaut, Quarkus provides a full-featured development stack that makes Java and its tremendous battle-tested ecosystem a first-class citizen for cloud-native applications.
With the Fast-JAR packaging’s clever usage of the filesystem and the JVM inner working, Quarkus pushes further the integration of Java apps within containerized environments. Thus allowing fast and reliable short delivery cycles adapted to modern requirements.
Resources
Official Quarkus doc: Fast-jar packaging
RedHat Dev blog: Build even faster quarkus applications with fast-jar