This year we plan to seriously develop the topics of containers, and . A logical continuation of these topics will be a discussion of the Quarkus framework, already on Habr. Today's article is dedicated not so much to the architecture of "subatomic super-fast Java," but rather to the prospects that Quarkus brings to Enterprise.

Java and the JVM are still extremely popular, but when working with serverless technologies and cloud-oriented microservices, Java and other languages for the JVM are used less frequently, as they take up too much memory and load too slowly, making them poorly suited for use with short-lived containers. Fortunately, this situation is starting to change thanks to Quarkus.
Super-fast subatomic Java has reached a new level!
42 releases, 8 months of community work, and 177 amazing developers resulted in the release in November 2019 , a release that marks an important milestone in the project's development and offers a plethora of cool features and capabilities (more details can be read in ).
Today we will discuss how Quarkus combines imperative and reactive programming models based on a single reactive core. We will start with a brief historical excursion and then take a closer look at what the duality of Quarkus's reactive core is and how -developers can take advantage of these benefits.
, and -functions – all of this is currently, as they say, on the rise. Recently, creating cloud-oriented architectures has become much simpler and more accessible; however, problems remain, especially for Java developers. For instance, in the case of serverless functions and microservices, there is a pressing need to reduce startup time, decrease memory consumption, and make their development a more convenient and pleasant task. In recent years, Java has made several improvements, such as enhanced ergonomics functionality for containers and more. However, achieving proper Java functionality in a container is still quite challenging. Therefore, we will start by examining some of the internal complexities of Java that are particularly acute when developing container-oriented Java applications.
Let's start by looking at the history.

Threads and Containers
Starting from version 8u131, Java has more or less begun to support containers through improvements in ergonomics functionality. In particular, the JVM now knows how many processor cores it is running on and can adjust thread pools accordingly—typically fork/join pools. This is certainly great, but let's say we have a traditional web application that uses HTTP servlets and runs in Tomcat, Jetty, etc. As a result, this application will assign a separate thread for each request, allowing it to block that thread while waiting for I/O operations, such as database calls, file access, or other services. This means that the size of such an application depends not on the number of available cores but on the number of simultaneous requests. Furthermore, this implies that quotas or limits in Kubernetes regarding the number of cores won't be much help here, and in the end, it will lead to throttling.
Memory Exhaustion
Threads are memory. And in-container memory limits are by no means a cure-all. Just start increasing the number of applications and threads, and sooner or later you will face a critical rise in context switch frequency and, as a consequence, a degradation of performance. Additionally, if an application uses traditional microservices frameworks, connects to a database, or employs caching, or somehow further consumes memory, you obviously need a tool that allows you to peek inside the JVM and see how it manages memory, without killing the JVM itself (e.g., XX:+UseCGroupMemoryLimitForHeap). Even though, starting from Java 9, the JVM has learned to recognize cgroups and adapt accordingly, reserving and managing memory remains quite a challenge.
Quotas and Limits
Java 11 introduced support for CPU quotas (like PreferContainerQuotaForCPUCount). Kubernetes also offers support for limits and quotas. Yes, all of this makes sense, but if the application again exceeds the allocated quota, we return to the point that the size—similar to traditional Java applications—is determined by the number of cores, with a separate thread allocated for each request, meaning the practical benefit of all this is minimal.
Moreover, using quotas and limits or the horizontal scaling features of the underlying Kubernetes platform does not solve the problem on its own. We simply end up wasting more resources on addressing the original issue or ultimately face resource overuse. If this is a high-load system in a public cloud, we almost certainly start using more resources than actually needed.
So what can be done about all this?
To put it simply, utilize asynchronous and non-blocking I/O libraries and frameworks like Netty, or Akka. They are much better suited for operation in containers due to their reactive nature. With non-blocking I/O, the same thread can handle multiple concurrent requests at once. While one request waits for I/O results, the processing thread is freed up to handle another request. When the I/O results finally come in, processing of the first request continues. By alternating request processing within the same thread, we can reduce the total number of threads and lower resource consumption for request handling.
With non-blocking I/O, the number of cores becomes a key parameter, as it determines the number of I/O threads that can run in parallel. When used correctly, this allows for effective load distribution among cores and the ability to handle higher loads with fewer resources.
How, is that everything?
No, there is more. Reactive programming helps utilize resources more effectively, but it also comes at a cost. In particular, the code will need to be rewritten according to non-blocking principles and avoid blocking I/O threads. This represents a completely different model of development and execution. Although there are many useful libraries available, it still requires a radical shift in thinking.
First, you need to learn how to write code that runs asynchronously. Once you start using non-blocking I/O, you need to explicitly specify what should happen when a response to a request is received. Simply blocking and waiting is no longer an option. Instead, you can pass callbacks, use reactive programming, or continuations. But that's not all: to use non-blocking I/O, you need non-blocking servers and clients, preferably everywhere. With HTTP, it's straightforward, but there are also databases, file systems, and much more.
While total end-to-end reactivity provides maximum efficiency, such a shift can be difficult to digest in practice. Therefore, the ability to combine reactive and imperative code becomes a necessary condition for:
- Effectively utilizing resources in the most loaded areas of the software system;
- Using simpler style code in its other parts.
Introducing Quarkus
Essentially, this is the essence of Quarkus – to combine reactive and imperative models within a single runtime environment.
At the core of Quarkus are Vert.x and Netty, on top of which a range of reactive frameworks and extensions are utilized to assist developers. Quarkus is designed to build not only HTTP microservices but also event-driven architectures. Thanks to its reactive nature, it works very efficiently with messaging systems (Apache Kafka, AMQP, etc.).
The trick lies in how to use the same reactive engine for both imperative and reactive code.

Quarkus excels in this regard. The choice between imperative and reactive programming is clear – use the reactive core for both. It greatly aids in fast non-blocking code that handles almost everything that goes through the event-loop thread (also known as the IO thread). However, if you have classic REST applications or client-side applications, Quarkus offers an imperative programming model. For example, HTTP support in Quarkus is built on using a non-blocking and reactive engine (Eclipse Vert.x and Netty). All HTTP requests received by your application initially go through the event loop (IO Thread) and are then sent to the part of the code that manages the requests. Depending on the destination, the request management code may be invoked in a separate thread (the so-called worker thread, used in servlet and Jax-RS cases) or use the original input/output thread (reactive route).

For connectors in message passing systems, non-blocking clients that operate on top of the Vert.x engine are used. Therefore, you can efficiently send, receive, and process messages from messaging middleware systems.
On the website A collection of good guides has been assembled to help you get started with Quarkus:
Additionally, we have prepared online practical lessons to familiarize you with various aspects of reactive programming, requiring only a browser; no IDE is necessary, and even a computer is not mandatory. You can find these lessons .
Useful Resources
- The Quarkus project website is
- The Quarkus project on GitHub is
- The Quarkus project Twitter account is
- The Quarkus project chat is
- The Quarkus project forums are !forum/quarkus-dev
10 video lessons on Quarkus to get up to speed
As mentioned on the website , , which combines - a Java stack oriented for GraalVM and OpenJDK HotSpot, built from the best Java libraries and standards.
To help you get acquainted with the topic, we have selected 10 video lessons that cover various aspects of Quarkus and examples of its use:
1. Introducing Quarkus: A next-generation Java framework for Kubernetes
Authors: Thomas Qvarnstrom and Jason Greene
The goal of the Quarkus project is to create a Java platform for Kubernetes and serverless environments, as well as to combine reactive and imperative programming models within a unified runtime, enabling developers to flexibly vary their approach while working with a wide range of distributed application architectures. Learn more from the introductory lecture below.

2. Quarkus: Ultra-Fast Subatomic Java
Author: Burr Sutter
The video tutorial from the DevNation Live online seminar demonstrates how to use Quarkus to optimize enterprise Java applications, APIs, microservices, and serverless functions in a Kubernetes/OpenShift environment, making them significantly smaller, faster, and more scalable.

3. Quarkus and GraalVM: Supercharging Hibernate to Extreme Speeds and Shrinking it to Subatomic Sizes
Author: Sanne Grinovero
From the presentation, you'll learn about the origins of Quarkus, how it works, and how it allows complex libraries like Hibernate ORM to be compatible with GraalVM native images.

4. Learning to Develop Serverless Applications
Author: Marthen Luther
The video below shows how to create a simple Java application using Quarkus and deploy it as a serverless application on Knative.

5. Quarkus: Code with Joy
Author: Edson Yanaga
A video guide to creating your first Quarkus project that explains why Quarkus is winning the hearts of developers.

6. Java and Containers - What Will Their Joint Future Look Like
Author: Mark Little
This presentation introduces the history of Java and explains why Quarkus is the future of Java.

7. Quarkus: Ultra-Fast Subatomic Java
Author: Dimitris Andreadis
An overview of the advantages of Quarkus that have gained recognition among developers: simplicity, ultra-high speeds, better libraries, and standards.

8. Quarkus and Subatomic Reactive Systems
Author: Clement Escoffier
With integration into GraalVM, Quarkus provides an ultra-fast development experience and a subatomic runtime environment. The author discusses the reactive side of Quarkus and how to utilize it for creating reactive applications and applications with data streaming.

9. Quarkus and Rapid Application Development in Eclipse MicroProfile
Author: John Clingan
By combining Eclipse MicroProfile and Quarkus, developers can create fully functional MicroProfile container applications that start in just a few milliseconds. This video thoroughly explains how to code a MicroProfile container application for deployment on the Kubernetes platform.

10. Java, "Turbo" version
Author: Marcus Biel
The author demonstrates how to use Quarkus to create super small and super fast Java containers, creating a real breakthrough, especially in serverless environments.

Source: habr.com
