Quarkus の紹介: Java 開発者が Supersonic Java に移行する理由
30 年近くにわたり、Java はエンタープライズ ソフトウェア開発の主流となってきました。その豊富なエコシステム、堅牢なオブジェクト指向基盤、Java 仮想マシン (JVM) によるプラットフォームの独立性、および Spring Boot などの歴戦のフレームワークにより、バックエンド インフラストラクチャの明白な王者となりました。
しかし、クラウドネイティブ アーキテクチャ、Kubernetes オーケストレーション、コンテナ化 (Docker)、サーバーレス コンピューティング (AWS Lambda、Knative) への移行により、高いメモリ オーバーヘッドと遅い起動時間という、従来の Java アプリケーション フレームワークの深刻な脆弱性が明らかになりました。
トラフィックの急増に対応してマイクロサービスがレプリカを 0 から 100 まで水平にスケールする必要がある場合、またはサーバーレス関数がオンデマンドで実行される場合、Java プロセスの起動を 3 ~ 10 秒待つことは許容できません。最新のクラウド インフラストラクチャでは、即時起動と軽量メモリ消費が求められます。これらの特性は従来、Go、Rust、Node.js などの言語に限定されていました。
Quarkus は、GraalVM および OpenJDK HotSpot 向けに特別に設計された Kubernetes ネイティブ Java フレームワークです。 「Supersonic Subatomic Java」 とも呼ばれる Quarkus は、Java アプリケーションのコンパイル、ブート、実行方法を根本的に再設計します。
この詳細なガイドでは、Java 開発者が Quarkus を採用する理由、Quarkus が 1 秒未満の起動時間とマイクロメモリの使用量をどのように達成するか、ビルド時間の最適化 のアーキテクチャの仕組み、および Quarkus を使用して Java で本番環境に対応したリアクティブ マイクロサービスを構築する方法について説明します。
1. 従来の Java のクラウドネイティブのジレンマ
Quarkus が存在する理由を理解するには、Spring Boot や Jakarta EE などの従来の Java フレームワークが内部でどのように動作するかを調べる必要があります。
A. 実行時の初期化コストが大きい
従来の Java フレームワークは、実行時の動的リフレクション、クラスパス スキャン、およびプロキシ生成に大きく依存しています。
- クラスパス スキャン: 起動時に、JVM はクラスパス内のすべての JAR ファイルをスキャンして、
@Component、@Service、@Controller、または@Entityなどの注釈を検出します。 - アノテーション処理とリフレクション: フレームワークはリフレクション (
Class.forName()、getDeclaredFields()) を使用して、Bean、構成プロパティ、および依存関係のメモリ内グラフを構築します。 - 動的プロキシの作成: CGLIB または ByteBuddy は、アスペクト指向プログラミング (AOP)、データベース トランザクション管理 (
@Transactional)、およびセキュリティ境界をサポートするために、ランタイム メモリに動的バイトコード プロキシを生成します。 - メタスペースと RSS のインフレ: すべてのメタデータ、反映されたクラス記述子、および生成されたプロキシは、JVM のメタスペースおよび常駐セット サイズ (RSS) 内のメモリに保持される必要があります。
この実行時リフレクション ループにはかなりの CPU サイクルが必要であり、ヒープ メモリの消費量が増大します。従来の Java の基本的な CRUD REST サービスは、アイドル時に 140MB ~ 300MB の RAM を簡単に消費し、**開始までに 3 ~ 8 秒かかります。
B. クラウド コンピューティングにおける金銭的ペナルティ
サーバーレスおよびコンテナ化された環境では、クラウド プロバイダーは、割り当てられたメモリ (GB) と 実行時間 (ミリ秒) という 2 つの指標に基づいて料金を請求します。
- コールド スタート: サーバーレス機能の起動に 5 秒かかる場合、エンドユーザーは顕著な遅延を経験し、5 秒間のアイドル起動計算に対して料金を支払います。
- 密度とポッドのスケーラビリティ: 16 GB の RAM を備えたワーカー ノードを備えた Kubernetes クラスターでは、メモリが不足する前に最大 40 個の従来の Spring Boot マイクロサービス インスタンスしか実行できません。各インスタンスが RAM を 15MB しか消費しない場合、同じノードで 800 を超えるインスタンスをホストできます。
2. Quarkus アーキテクチャ: 作業を実行時から構築時に移行
Quarkus は、動的操作をランタイムからビルドタイムに移行するという、根本的なアーキテクチャ パラダイム シフトを通じてクラウド ネイティブのジレンマを解決します。
ビルド時の処理 (事前最適化)
アプリケーションが起動するたびにクラスパスのスキャン、アノテーションの解析、Bean グラフの接続を実行する代わりに、Quarkus はこれらすべての重い操作をビルドフェーズ (mvn package または ./gradlew build) 中に 1 回実行します。
- 拡張機能のアーキテクチャと構築手順: Quarkus は、プラグ可能な拡張フレームワークを使用します。アプリケーションをコンパイルするときに、Quarkus 拡張機能はアノテーションを解析し、最適化された静的バイトコードを生成し、依存関係注入グラフを事前に解決します。
- 事前にベイクされたメタデータ: すべての依存関係注入メタデータは事前に計算されます。アプリケーションが起動すると、Quarkus は、リフレクションの呼び出しやクラスパスのスキャンを行わずに、プリコンパイルされたクラスを直接インスタンス化します。
- デッド コードの除去 (ツリー シェイキング): ビルド プロセス中に、Quarkus はアプリケーションで使用されていないクラス、メソッド、およびライブラリを特定し、それらを完全に削除します。
アプリケーション JAR またはネイティブ バイナリが生成されるまでに、実行時のオーバーヘッドはすべて除去されています。 JVM は、事前に設定された静的バイトコードをロードするだけで、即座に開始されます。
3. GraalVM ネイティブ イメージと OpenJDK HotSpot
Quarkus はデュアル実行モデルを提供します。標準の OpenJDK HotSpot では非常に高速に実行されますが、GraalVM ネイティブ イメージにコンパイルされると潜在的なパフォーマンスが最大に達します。
+-----------------------------------------------------------------------+
| Java Source Code (.java) |
+-----------------------------------------------------------------------+
|
v (Standard javac)
+-----------------------------------------------------------------------+
| Bytecode (.class) |
+-----------------------------------------------------------------------+
/ \
/ \
v v
+----------------------------------+ +----------------------------------+
| OpenJDK HotSpot JVM | | GraalVM Native Image (AOT) |
| - JIT Compilation (C1/C2) | | - Substrate VM |
| - Dynamic Class Loading | | - No Classpath Scanning |
| - Fast throughput, longer boot | | - Millisecond boot, tiny RAM |
+----------------------------------+ +----------------------------------+
Ahead-of-Time (AOT) コンパイルとサブストレート VM
GraalVM ネイティブ イメージは Java バイトコードを取得し、それを OS 固有のスタンドアロン実行可能バイナリ (Linux では ELF バイナリ、macOS では Mach-O、Windows では EXE) に直接コンパイルします。
- クローズドワールドの仮定: GraalVM は、到達可能なすべてのコード、クラス、リソースがビルド時に既知であることを前提としています。
- Substrate VM: ネイティブ実行可能ファイルには Substrate VM と呼ばれる小型ランタイム エンジンが組み込まれており、完全な JVM インスタンスを起動せずにメモリ管理、スレッド スケジューリング、ガベージ コレクションを処理します。
- リフレクション オーバーヘッドゼロ: Quarkus はビルド時にリフレクション構成とプロキシ定義を準備するため、これまでネイティブ GraalVM ビルドで必要とされてきた手動構成ファイルを使用しなくても、GraalVM ネイティブ イメージのコンパイルはスムーズに成功します。
4. パフォーマンスのベンチマーク: 経験的証拠
パフォーマンスの明らかな対照を説明するために、標準的な REST + データベース CRUD サービスを実行する 3 つの Java ランタイム構成にわたる標準的な業界ベンチマークの比較を調べてみましょう。
- 従来のクラウドネイティブ スタック (従来の JVM / Spring Boot)
- OpenJDK HotSpot 上の Quarkus
- GraalVM ネイティブ イメージ上の Quarkus
パフォーマンス概要表
| メトリック | 従来のスタック (JVM) | Quarkus (ホットスポット JVM) | Quarkus (GraalVM ネイティブ) |
|---|---|---|---|
| REST RSS メモリ | ~140MB | ~74MB | ~13MB |
| REST + CRUD RSS メモリ | ~218MB | ~112MB | ~35MB |
| REST 起動時間 | ~4.3秒 | ~0.98秒 | ~0.014 秒 (14ms) |
| REST + CRUD の起動時間 | ~9.5秒 | ~2.0秒 | ~0.042 秒 (42ms) |
| 実行可能なアーティファクト | 大きな脂肪 JAR (~50MB) | 最適化された JAR (~20MB) | スタンドアロン ネイティブ バイナリ (~30MB) |
ネイティブ イメージにコンパイルされた Quarkus は 14 ミリ秒 (瞬きよりも速い) で起動し、消費する RAM はわずか 13 MB であることに注目してください。これにより、Java はサーバーレスおよびクラウドネイティブのデプロイメントにおいて Go や Rust と完全に競争できるようになります。
5. リアクティブおよびインペラティブ デュアルコア エンジン
歴史的に、Java 開発者は 2 つの相互に排他的なプログラミング モデルから選択する必要がありました。
- 命令型 (リクエストごとのスレッド): 標準の JDBC ドライバーと同期 REST エンドポイントを使用した、シンプルで読みやすいブロッキング コード。
- リアクティブ (イベント ループ): 高スループットの非同期、ノンブロッキング コード (RxJava、Project Reactor など) ですが、複雑なコールバック チェーンと困難なデバッグで知られています。
Quarkus は、Eclipse Vert.x と Netty を搭載した単一の統合エンジンの下で両方の世界を統合します。
+---------------------------------+
| Client HTTP Request |
+---------------------------------+
|
v
+---------------------------------+
| Eclipse Vert.x I/O |
| (Event Loop) |
+---------------------------------+
/ \
/ \
v v
+-------------------+ +-------------------+
| Reactive Endpoint | |Blocking Endpoint |
| (Event Loop) | | (Worker Thread) |
| - Mutiny (Uni/Multi)| | - Standard JDBC |
| - Non-blocking | | - Imperative Code |
+-------------------+ +-------------------+
Quarkus では、ノンブロッキング I/O が基盤です。従来のブロッキング コードを作成すると、Quarkus はその実行をマネージド ワーカー スレッド プールに自動的にディスパッチします。 SmallRye Mutiny (Uni<T> および Multi<T>) のようなリアクティブ型を使用する場合、実行は高性能のノンブロッキング イベント ループ スレッドに留まります。
6. 開発者の喜び: ライブコーディングと開発サービス
Quarkus は、実行時のパフォーマンスだけでなく、退屈なビルド、テスト、再起動のフィードバック ループを排除するように設計された革新的な開発者エクスペリエンスを提供します。
A. ゼロリスタート ライブ コーディング (quarkus:dev)
mvn quarkus:dev を実行すると、Quarkus はライブコーディング モードを起動します。 Java ファイルの編集、プロパティの変更、HTML テンプレートの変更、データベース スキーマの更新を行うことができます。
次回ブラウザまたはターミナルで HTTP リクエストをトリガーすると、Quarkus はファイルの変更を検出し、ビルド ステップを再適用し、500 ミリ秒未満でアプリケーションをホットリロードします。開発中にアプリケーション サーバーを手動で停止して再起動する必要はありません。
B. Quarkus 開発サービス (ゼロ構成テストコンテナ)
マイクロサービスを PostgreSQL データベース、Kafka ブローカー、または Redis キャッシュに接続するには、通常、docker-compose.yml ファイルを作成し、ローカル データベース ポートを構成する必要があります。
Quarkus 開発サービスを使用すると:
- Quarkus がデータベースの依存関係 (
quarkus-reactive-pg-clientなど) を検出したが、データベース URL がapplication.propertiesに設定されていない場合、Quarkus は バックグラウンドで Testcontainers 経由で PostgreSQL を実行する Docker コンテナを自動的に起動します。 - 実行中のアプリケーションに接続資格情報が自動的に挿入されます。
- 開発モードを停止すると、コンテナー自体がクリーンアップされます。
7. 実践的なウォークスルー: 本番環境に対応したリアクティブ Quarkus サービスの構築
Hibernate Reactive with Panache を使用して PostgreSQL データベースに接続された REST API を公開する、クリーンで高性能の Quarkus マイクロサービスを Java で構築してみましょう。
ステップ 1: プロジェクトの依存関係 (pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ghaznix.quarkus</groupId>
<artifactId>user-service</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<compiler-plugin.version>3.13.0</compiler-plugin.version>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>3.15.1</quarkus.platform.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- RESTEasy Reactive for high-performance HTTP endpoints -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>
<!-- Hibernate Reactive with Panache for active-record data access -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-reactive-panache</artifactId>
</dependency>
<!-- Reactive PostgreSQL Driver -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
<!-- Quarkus SmallRye OpenAPI / Swagger UI -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<!-- Testing -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
ステップ 2: リアクティブエンティティを定義する (UserEntity.java)
Quarkus は、Hibernate 上の Active-Record パターン実装である Panache を使用してデータ アクセスを簡素化しました。
package com.ghaznix.quarkus.entity;
import io.quarkus.hibernate.reactive.panache.PanacheEntity;
import io.smallrye.mutiny.Uni;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import java.time.Instant;
@Entity
@Table(name = "users")
public class UserEntity extends PanacheEntity {
@NotBlank(message = "Username cannot be blank")
@Column(unique = true, nullable = false)
public String username;
@Email(message = "Email must be valid")
@Column(unique = true, nullable = false)
public String email;
@Column(nullable = false)
public String role;
@Column(name = "created_at", nullable = false, updatable = false)
public Instant createdAt = Instant.now();
/**
* Helper method to find a user reactively by email.
*/
public static Uni<UserEntity> findByEmail(String email) {
return find("email", email).firstResult();
}
}
ステップ 3: リアクティブ REST リソース (UserResource.java) を実装する
RESTEasy Reactive と SmallRye Mutiny を使用すると、HTTP エンドポイントはノンブロッキング スレッドで完全に非同期で動作します。
package com.ghaznix.quarkus.resource;
import com.ghaznix.quarkus.entity.UserEntity;
import io.quarkus.hibernate.reactive.panache.Panache;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.net.URI;
import java.util.List;
@Path("/api/v1/users")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApplicationScoped
public class UserResource {
@GET
public Uni<List<UserEntity>> getAllUsers() {
return UserEntity.listAll();
}
@GET
@Path("/{id}")
public Uni<Response> getUserById(@PathParam("id") Long id) {
return UserEntity.<UserEntity>findById(id)
.onItem().ifNotNull().transform(user -> Response.ok(user).build())
.onItem().ifNull().continueWith(() -> Response.status(Response.Status.NOT_FOUND).build());
}
@POST
public Uni<Response> createUser(@Valid UserEntity user) {
return Panache.withTransaction(user::persist)
.replaceWith(() -> Response.created(URI.create("/api/v1/users/" + user.id))
.entity(user)
.build());
}
@DELETE
@Path("/{id}")
public Uni<Response> deleteUser(@PathParam("id") Long id) {
return Panache.withTransaction(() -> UserEntity.deleteById(id))
.map(deleted -> deleted
? Response.noContent().build()
: Response.status(Response.Status.NOT_FOUND).build());
}
}
ステップ 4: アプリケーション構成 (application.properties)
# Quarkus Application Configuration
quarkus.application.name=user-service
quarkus.http.port=8080
# Database Schema Management (Automatically managed by Dev Services in dev mode)
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=true
# SmallRye OpenAPI & Swagger UI Configuration
quarkus.smallrye-openapi.path=/swagger-ui
quarkus.swagger-ui.always-include=true
データベース URL、ユーザー名、またはパスワードを構成していないことに注意してください。 ./mvnw quarkus:dev を実行すると、Quarkus は自動的に PostgreSQL を検出し、Docker コンテナを起動し、データベース スキーマ テーブルを設定し、http://localhost:8080/swagger-ui で Swagger UI を開きます。
ステップ 5: ネイティブ実行可能ファイルのビルドと実行
インスタント ライブ コーディング開発モードで実行するには:
./mvnw quarkus:dev
Docker コンテナ内で GraalVM を使用してネイティブ Linux バイナリを構築するには (ローカルの GraalVM インストールは必要ありません):
./mvnw package -Dnative -Dquarkus.native.container-build=true
結果のバイナリを OS 上で直接起動するには:
./target/user-service-1.0.0-SNAPSHOT-runner
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2026-08-26 01:37:15,102 INFO [io.quarkus] (main) user-service 1.0.0-SNAPSHOT native (powered by Quarkus 3.15.1) started in 0.016s. Listening on: http://0.0.0.0:8080
2026-08-26 01:37:15,103 INFO [io.quarkus] (main) Profile prod activated.
2026-08-26 01:37:15,103 INFO [io.quarkus] (main) Installed features: [cdi, hibernate-reactive, panache, reactive-pg-client, resteasy-reactive, resteasy-reactive-jackson, smallrye-openapi]
0.016秒起動!
8. 戦略的機能の比較: Quarkus と Spring Boot
| 能力・特徴 | 従来の Spring Boot 3.x | クォーカス 3.x |
|---|---|---|
| 主要なアーキテクチャ | ランタイムリフレクションとダイナミックスキャン | ビルド時の処理と AOT の最適化 |
| ネイティブ コンパイル | Spring Native (複雑なヒントが必要) | ファーストクラスの GraalVM ネイティブ統合 |
| 起動速度 (ネイティブ) | ~0.1~0.5秒 | ~0.01 ~ 0.04 秒 |
| メモリ RSS フットプリント | 140MB~300MB | 13MB~40MB |
| 開発環境 | DevTools 経由のホットスワップ (限定的) | ゼロリスタート ライブ コーディング (quarkus:dev) |
| サードパーティのサービス | 手動の Docker / Testcontainers 構成 | 自動開発サービス (ゼロ構成コンテナ) |
| 標準サポート | 春のエコシステム固有 | Jakarta EE および MicroProfile 標準仕様 |
| リアクティブパラダイム | Spring WebFlux (別のスタック) | 統合エンジン (Vert.x コア / リアクティブ + インペラティブ) |
9. 結論: Quarkus に切り替える時期が来ていますか?
Quarkus は単なる Web フレームワークではありません。これは、クラウドネイティブ時代に向けた Java の進化を表しています。 Quarkus は、ビルド時の最適化と GraalVM ネイティブ コンパイルを組み合わせることで、最新のマイクロサービスやサーバーレス機能に対して Java は遅すぎる、またはメモリが多すぎるという従来の固定概念を無効にします。
Quarkus を選択する必要があるのはどのような場合ですか?
- サーバーレスおよびイベント駆動型アプリケーション: マイクロサービスを AWS Lambda、GCP Cloud Run、または Knative にデプロイしている場合、Quarkus ネイティブ バイナリによりコールド スタートの問題が完全に排除されます。
- 高密度 Kubernetes クラスタ: インフラストラクチャの請求額がクラスタの RAM 消費量によって占められている場合、サービスを Quarkus に移行することでメモリ コストを最大 75% 削減できます。
- リアクティブ マイクロサービス: ノンブロッキング ストリーミング (Kafka、gRPC、WebSocket) を必要とする高スループット システムを構築する場合、Quarkus はすぐに最高レベルのパフォーマンスを提供します。
Java は、起動の遅さやランタイムの肥大化によって固定されることはなくなりました。 Quarkus を使用すると、Java 開発者は 超音速と亜原子的なフットプリントを備えたクラウドネイティブ アプリケーションを構築できます。
Tags
Empower Your Digital Presence & Workflows
Explore top-tier tools built by Ghaznix to streamline your links, surveys, and brand growth.