You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2026/06/19 13:31:14 UTC

(juneau) branch docs updated: docs: GraalVM native-image feasibility verdict + Docker layering guidance

This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch docs
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/docs by this push:
     new 77b9e2fc3b docs: GraalVM native-image feasibility verdict + Docker layering guidance
77b9e2fc3b is described below

commit 77b9e2fc3b89d8bc7b136608d225658f340ee98d
Author: James Bognar <ja...@apache.org>
AuthorDate: Fri Jun 19 09:31:08 2026 -0400

    docs: GraalVM native-image feasibility verdict + Docker layering guidance
---
 pages/release-notes/10.0.0.md                   |  4 +++
 pages/topics/17.02.NativeImageAndLayeredJars.md | 43 +++++++++++++++++++++++++
 sidebars.ts                                     |  5 +++
 3 files changed, 52 insertions(+)

diff --git a/pages/release-notes/10.0.0.md b/pages/release-notes/10.0.0.md
index e9408bc399..75f203bb08 100644
--- a/pages/release-notes/10.0.0.md
+++ b/pages/release-notes/10.0.0.md
@@ -202,6 +202,10 @@ A reactor-consistency guard (`scripts/check-bom-completeness.py`, wired into the
 
 See the new [Dependency Management (BOM & Bundles)](/docs/topics/DependencyManagement) topic page for usage and the full explicit-over-magic rationale.
 
+#### GraalVM native-image feasibility verdict + Docker layering guidance
+
+A feasibility assessment of GraalVM **native-image** support for Juneau's reflection-heavy marshalling/bean core landed a **CONDITIONAL GO** verdict: all reflection is funnelled through one wrapper layer (`org.apache.juneau.commons.reflect.*`, single `setAccessible()` choke point) with no `Unsafe`/`MethodHandle`/bytecode generation, and the `BeanContext`/`ClassMeta` model already computes the exact member set reachability metadata needs — making a Juneau-authored metadata emitter realist [...]
+
 ### juneau-petstore (new module family)
 
 Three new modules under a top-level `juneau-petstore/` aggregator together form the canonical Juneau petstore showcase application.  The legacy `juneau-examples-rest{,-jetty,-springboot,-jetty-ftest}` family of modules has been retired in this release in favor of the petstore family — see the **Breaking Changes** section below.
diff --git a/pages/topics/17.02.NativeImageAndLayeredJars.md b/pages/topics/17.02.NativeImageAndLayeredJars.md
new file mode 100644
index 0000000000..19c2fbe9ea
--- /dev/null
+++ b/pages/topics/17.02.NativeImageAndLayeredJars.md
@@ -0,0 +1,43 @@
+---
+title: "GraalVM Native Image & Docker Layering"
+slug: NativeImageAndLayeredJars
+---
+
+This page covers two packaging concerns for Juneau applications: **Docker image layering** (a concrete recommendation you can apply today) and **GraalVM native-image** support (a feasibility assessment with a forward plan).
+
+## Docker image layering
+
+Juneau itself ships **libraries**, not runnable applications, so there is no Juneau-side fat-jar to layer. Layering happens in *your* deployable application image. Two practical levers:
+
+- **Spring Boot apps** — `spring-boot-maven-plugin`'s `repackage` goal produces a [layered jar](https://docs.spring.io/spring-boot/reference/packaging/efficient.html) by default (since Spring Boot 2.4), separating slow-changing dependency layers from your fast-changing application classes. Combined with a multi-stage Dockerfile using `java -Djarmode=tools -jar app.jar extract --layers`, Docker caches the dependency layer across rebuilds. The Juneau Spring Boot petstore sample is built this way.
+- **Embedded-Jetty / plain-jar apps** — order your Dockerfile `COPY` steps coarsest-changing first: copy the dependency jars (which include the stable Juneau artifacts) in an earlier layer than your application jar, so a code-only change re-uploads only the small application layer. The external [starter projects](/docs/topics/StarterProjects) demonstrate this Dockerfile shape.
+
+Depending on Juneau through the version-aligned [BOM and curated bundles](/docs/topics/DependencyManagement) keeps the dependency layer stable and reproducible across rebuilds, which is what makes the cache hit reliable.
+
+## GraalVM native-image — feasibility verdict
+
+Juneau's marshalling/bean core is reflection-heavy, so native-image (closed-world AOT) support is non-trivial. A feasibility assessment was performed against the reflective source; the verdict is **CONDITIONAL GO**.
+
+### Why "conditional go", not "no-go"
+
+All of Juneau's reflection flows through a single wrapper layer — `org.apache.juneau.commons.reflect.*` (`ClassInfo` / `MethodInfo` / `FieldInfo` / `ConstructorInfo`) with one `setAccessible()` choke point in `AccessibleInfo` — and there is **no `sun.misc.Unsafe`, no `MethodHandle`/`VarHandle`, and no bytecode generation** anywhere in main source. The blockers are the *standard* native-image reflection blockers, not anything pathological. Critically, the same `BeanContext` / `BeanMeta` / [...]
+
+### The hard blockers (all standard, all addressable)
+
+1. **Open-world bean reflection** — every marshalled bean's full member set must be registered; application bean types are unknowable at Juneau-build time. There is no "zero-config native Juneau" — consumers always need a generation step.
+2. **User-supplied dynamic-proxy interface sets** (`@Remote` clients, interface beans) — proxy metadata can't be derived from Juneau's bytecode; it comes from the GraalVM tracing agent or explicit declaration.
+3. **`_type` dictionary class resolution** via `Class.forName` — classes reachable only through a serialized `_type` string are invisible to static analysis and must be registered by name.
+4. **Reflective swap/converter/DI instantiation** through `BeanInstantiator`.
+5. **Classpath resource + NLS `ResourceBundle` loading** — broad but low-risk (regex resource includes cover it).
+
+SPIs / `ServiceLoader` usage, despite intuition, is the *easiest* category — finite and statically known.
+
+### Recommended path (committed follow-on)
+
+The maintainer-approved direction is **option (b)**: a native-image-ready `juneau-marshall` **core** (JSON/XML/HTML/UON + swaps + dictionaries), driven by a Juneau-authored reachability-metadata emitter built on `BeanContext` introspection, with the GraalVM **tracing agent** covering the statically-invisible parts (`@Remote`/interface-bean proxies, `_type` dictionary classes). Target the modern unified `reachability-metadata.json` format, delivered as a **Maven plugin goal / module** the [...]
+
+The REST server (embedded Jetty/Tomcat, `ServletContainerInitializer`, transport providers) is **deferred** — most of its residual native-image risk lives in third-party dependencies, not Juneau's own code.
+
+Rough effort: a minimal single-bean JSON round-trip to native is **S** (~1–3 days); a generally-usable native marshalling core is **L** (~3–6 weeks); the full framework including `@Remote` proxies + REST server is **XL** and out of scope.
+
+> This assessment is a **feasibility verdict**, not a shipped feature. The native-image emitter is tracked as a dedicated committed follow-on; native-image builds of Juneau are not yet supported.
diff --git a/sidebars.ts b/sidebars.ts
index bfe4e2e473..f74ac0f497 100644
--- a/sidebars.ts
+++ b/sidebars.ts
@@ -2121,6 +2121,11 @@ const sidebars: SidebarsConfig = {
 							id: 'topics/17.01.DependencyManagement',
 							label: '17.1. Dependency Management (BOM & Bundles)',
 						},
+						{
+							type: 'doc',
+							id: 'topics/17.02.NativeImageAndLayeredJars',
+							label: '17.2. GraalVM Native Image & Docker Layering',
+						},
 					],
 				},
 				{