Java Platform Cross-Cutting Q&A: Modules, Build Tools, Lombok, and Compatibility Discipline#
This is a multi-topic architect Q&A digest aimed at senior engineers; jump to the question you care about. Below, normative wording from specifications such as JEP 261 is kept distinct from on-stage engineering judgment by the speakers.

Why has module adoption been slow?#
Context
The Java Platform Module System (JPMS) has offered strong encapsulation, reliable configuration, and linkable images since JDK 9, yet adoption among libraries and applications has stayed comparatively low. The floor question was blunt: design failure, or an ecosystem that has not caught up?
Key points
Why
If the build chain does not make --module-path, module-info.java, --add-exports for the unnamed module, and related options the “default correct path,” even strong JDK machinery is hard to land. Alex Buckley (speaker opinion) cited Java Agents as a microcosm: easy to attach on the command line via classpath, but in Maven/Gradle often wrapped as “yet another dependency jar.” Today’s payoff is mostly at evolution boundaries and security encapsulation; performance wins are largely deferred to the future, and teams lack migration incentive when tooling is awkward.
Mechanism / constraints
JEP 261 is explicit: module path semantics differ from the class path; code on the classpath enters the unnamed module with weaker encapsulation than named modules. Link-time assembly is covered by JEP 282 and jlink.
How to
javac --module-path lib --module-source-path src -d out \
--add-modules com.example.app
java --module-path out:lib -m com.example.app/com.example.Main
Common misconceptions
Equating “modules are hard” with “JPMS is badly designed”; more often, build/test/Agent plugins still orchestrate around a classpath mindset.
Further reading


jlink vision, library modularization, and 8→11 pain#
Context
The ideal path is to trim a runtime image with jlink containing only java.base and application dependency modules, then ship that into a container; in practice, many third-party libraries still ship as non-modular jars.
Key points
Why
Speaker opinion: without libraries modularizing, applications have little incentive for end-to-end modularization and jlink images. Much 8→11 breakage came from internal API encapsulation starting with JEP 260 (and later JEP 403 strong encapsulation)—not JPMS alone. On sun.misc.Unsafe: JEP 260 lists it among critical APIs still not encapsulated in JDK 9; JEP 403 states that under strong encapsulation sun.misc.Unsafe will remain—inconsistent with rumors that “Unsafe is gone”; what breaks are other internal API consumers.
Mechanism / constraints
jlink --module-path $MODPATH --add-modules com.app,jdk.unsupported \
--launcher app=com.app/com.app.Main --output runtime
How to
First verify whether dependencies still reflect into sun.* / jdk.internal.*; then decide whether to author module-info or rely on automatic module names.
Common misconceptions
Treating frameworks such as Spring as “already modularized” industry-wide (mentioned in this session, not verified against OpenJDK docs); ignoring the gap between automatic modules and real module-info.
Further reading


Why do libraries on the classpath “see through” encapsulation by default?#
Context
JDK modules control visibility with exports; a conventional jar the author publishes, if the user places it on the classpath, lands in the unnamed module as a whole, and package-level “privacy” remains fragile under reflection. The questioner asked whether that is fair to library authors.
Key points
Why
JEP 261: classpath code lives in the unnamed module and boundaries can be relaxed via --add-exports pkg=ALL-UNNAMED and similar. Speaker opinions diverged: Alex Buckley said whoever runs the process has the most choice and should be steered clearly toward the module path; Ron Pressler said classpath and module path are peers, with no single “default”; Brian Goetz acknowledged the default experience is problematic—the long-term direction is to gradually weaken classpath habits, but that angers some users, so the platform balances tightening vs. compatibility (“damned if you do, damned if you don’t”).
Mechanism / constraints
The specification describes mechanism differences, not “fairness.”
How to
If library authors want users on the module path: document --module-path startup examples in README and build artifacts; do not assume “package-private = JDK-strong encapsulation.”
Common misconceptions
Expecting the JDK to offer a symmetric strong-encapsulation switch for third-party jars on par with platform modules—the current strategy favors ecosystem migration over symmetric switches.
Further reading

Lombok: less boilerplate, or a compiler citizenship problem?#
Context
Enterprises still push Lombok hard on Java 25; the panel was asked: enemy, ally, or something that will age out naturally?
Key points
Why
Brian Goetz (speaker opinion): the boilerplate pain Lombok targets is real, but implementing via bytecode/AST rewriting through interfaces not specified in the JLS/JVMS is “bad citizenship” toward the compiler ecosystem; a fully rule-abiding parallel universe exists—it is a tool-author choice. It binds to mutable JavaBean + getter/setter semantics, at odds with years of platform advocacy for immutability and explicit construction; needing delombok for Javadoc is a smell. More likely to slow than accelerate style modernization. The official path is javac annotation processing (-processor, -processorpath); Immutables, AutoValue, etc. follow the annotation-processor route (listed as speaker opinion).
Mechanism / constraints
OpenJDK docs do not evaluate Lombok; they only define the annotation-processing extension point.
How to
javac -processor com.google.auto.value.processor.AutoValueProcessor \
-classpath auto-value.jar:.
Common misconceptions
Equating “less code” with “zero cost to compiler integration”; depending on preview or private compiler hooks for a library’s public API.
Further reading
- javac manual — Annotation Processing
- Project Lombok official site (implementation details per project docs)


When build tools lag the JDK, should the language group take over?#
Context
Go ships go build with the language; on the Java side, Maven/Gradle support for preview features and the module path often lags—should the JDK team ship an “official build”?
Key points
Why
Brian Goetz (speaker opinion): historically prioritized JDK-exclusive capabilities (module linking, preview switches), but acknowledged the community has delivered poorly on build tools and may have to shift resources from language/libraries—already high priority. Alex Buckley (speaker opinion): “the community has fallen down” is not individual fault of Maven/Gradle maintainers; many commercial users barely fund these projects—fund the toolchain via foundations and similar channels. Mechanistic corroboration: preview requires javac --enable-preview and runtime --enable-preview (JEP 12); build plugins must pass them through.
How to
Lock --release + --enable-preview in CI templates for Maven maven-compiler-plugin / Gradle JavaCompile; when upgrading the JDK, run a module/preview compatibility matrix for dependencies first.
Common misconceptions
Waiting for Oracle to ship a single official Maven replacement—not promised in this session; more realistic levers are funding and plugin quality.
Further reading

Will compatibility ever be dropped for a “Java Next”?#
Context
Serialization, legacy concurrency primitives, and type-system historical baggage make developers hit walls often; the community occasionally fantasizes about “rewriting Java.”
Key points
Why
Brian Goetz (speaker opinion): no skipping Java 28/29 for a vague “Java Next” that throws compatibility away; if a change is worth doing, it comes with an actionable migration path and deliberate redesign, not bait-and-switch. “Compatibility—we’re all about compatibility”; breakage cost is enormous—worthwhile changes use multi-phase migration. Side note: JEP 223 reflects version-number and release cadence discipline, not a complete charter of compatibility philosophy.
Mechanism / constraints
Platform capabilities enter via JEPs incrementally (preview / incubator / final), not big-bang replacement.
Common misconceptions
Equating slow language evolution with the team “being afraid to change”; many changes stall on ecosystem migration cost, not lack of ideas.
Further reading


What belongs in the JDK vs. what stays in the ecosystem?#
Context
Why was there no built-in HTTP client years ago? Why not “move Jackson into” the JDK?
Key points
Brian Goetz (speaker opinion): with limited people, prioritize what only the JDK can do (class-file API, VM semantics), then competitive gaps, then subjective community ROI. Paul Sandoz (speaker opinion): also whether the JDK increasingly needs the capability—e.g. virtual-thread dumps already support JSON (jcmd Thread.dump_to_file -format=json); “configure the JDK with JSON” remains aspirational. Brian: will not plop ecosystem libraries verbatim into the JDK—historically several moves ended in expensive removal; a library’s “best right now” vs. the JDK’s “X for decades” are different beasts (ASM vs. class-file API analogy, speaker opinion). Verified example: JEP 321 standardized the HTTP Client from JEP 110 incubator to java.net.http.
Further reading
How much longer will structured concurrency stay in preview?#
Context
StructuredTaskScope has been through multiple preview rounds; developers want to know when it can ship in library APIs.
Key points
Ron Pressler (speaker opinion): very close to dropping preview, but a few preview points remain—possibly one more preview round; fine for applications under preview, not recommended for libraries to harden on preview APIs. Alex Buckley (speaker opinion): “feedback” means real trial experience, not armchair redesign; HTTP Client analogy—quiet after Java 9, feedback flood near the end, Java 11 finalization still in use; JEP 517 shows HTTP/3 still evolving. Docs: JEP 533 (seventh preview in JDK 27) states preview the API once more, more concrete than casual remarks.

Further reading

When does Project Babylon enter the formal process?#
Context
Code reflection, GPU/SQL, and other experimental directions—what should the community try?
Key points
Speaker opinion: JEPs already in Submitted status, advancing via incubator; timeline “ready when ready.” Verifiable docs: Project Babylon, JEP 8361105 — Code reflection (incubator, Submitted), module jdk.incubator.code, enable example javac --add-modules jdk.incubator.code. Alex Buckley (speaker opinion): Babylon needs community feedback more than most features.
Further reading
Will the Stream API get a systematic performance rewrite?#
Context
Stream polymorphism and boxing add overhead; in practice, loops are often recommended instead.
Key points
Brian Goetz (speaker opinion): design favors clear expression; most workloads are small—deep Stream framework ROI is low; historically chose human readability over machine-friendliness; Valhalla and others may open later paths. John Rose (speaker opinion): treat as loop customization; megamorphic cliff limits component reuse; Babylon/stream fusion (Scala precedent) may give the JIT better static structure—years-scale, not the next minor release. Note: Stream shipped in Java 8 java.util.stream; do not cite today’s JEP 189 (Shenandoah GC) as Stream evidence.
Further reading

Can AI accelerate OpenJDK, and how do architects use it?#
Context
Huge backlog, heavy conformance-test maintenance—can AI agents share the load?
Key points
Brian Goetz (speaker opinion): can help; how matters, still unsettled. Alex Buckley (speaker opinion): OpenJDK is not a casual GitHub repo for drive-by PRs—do not harass maintainers with AI agents; process in the OpenJDK Developers’ Guide (OCA, sponsor, JBS). Paul Sandoz et al. (speaker opinion): experimenting with AI to update tests as specs change. John Rose (speaker opinion): cites Amdahl’s law—70% faster does not make the remaining 30% free; does not trust agents, nor plans to soon; guard against “tests that always pass” gaming.
Further reading

Can compact object headers materially shrink the heap?#
Context
JEP 519 (productized in JDK 25) continues JEP 450: object headers from 96–128 bit down to 64 bit (8 bytes), saving roughly 4 bytes per object vs. a common 12-byte header.
Key points
John Rose et al. (speaker opinion): theoretically reclaimable memory, practically depends on fragmentation and allocation patterns—try it, measure it. JEP 450 cites Lilliput experiments: live data often down ~10%–20%, do not state as a fixed ratio. Enable (JDK 24 experimental example): -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders; JDK 25 see JEP 519 body. Default-on timeline in JEP 534 (proposed JDK 27)—not verified as delivered at capture time.
Further reading

References and further reading#
- JEP 261 — Java Platform Module System
- JEP 282 — jlink: The Java Linker
- jlink command reference
- JEP 260 — Encapsulate Most Internal APIs
- JEP 403 — Strongly Encapsulate JDK Internals (Unsafe retained)
- JEP 12 — Preview Features: compile and runtime dual switches
- JEP 533 — Structured Concurrency (Seventh Preview, JDK 27)
- JEP 8361105 — Code reflection incubator draft
- JEP 321 — Standard HTTP Client API
- JEP 517 — HTTP/3 for the HTTP Client API
- javac manual — Annotation processing and
--enable-preview - OpenJDK Developers’ Guide — contribution and sponsor process
- JEP 450 / JEP 519 — Compact object headers experimental and product
- JEP 445 / JEP 495 — Unnamed classes and instance
mainpreview chain - JEP 454 — Foreign Function & Memory API
Depth boundary: this article summarizes a ~58-minute breadth Q&A, not a JPMS/Maven implementation tutorial, and does not dissect Lombok’s internal hooks; where marked “speaker opinion,” validate against your JDK version and dependency tree.



