Quarkus’ Fast-JAR packaging

3 minute(s) read

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:

  1. Splitting the App and it’s dependencies into several folders.
  2. 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

quarkus_fastjar_anatomy.png

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.

container_layers.png

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

Written by

Jean-Baptiste Roux

Software craftsman