Skip to content

feat: add a JPMS module descriptor#25

Merged
dfa1 merged 2 commits into
mainfrom
feat/jpms-module-info
Jul 12, 2026
Merged

feat: add a JPMS module descriptor#25
dfa1 merged 2 commits into
mainfrom
feat/jpms-module-info

Conversation

@dfa1

@dfa1 dfa1 commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Make zstd a proper named module: module io.github.dfa1.zstd { exports io.github.dfa1.zstd; }.

Why

Modular consumers can now requires io.github.dfa1.zstd and grant native access to just this module (--enable-native-access=io.github.dfa1.zstd) instead of the blanket ALL-UNNAMED. (The flag is still required either way — FFM downcalls are restricted.)

Notes / gotchas handled

  • Module-name lint. javac flags dfa1 (terminal digit, possibly version-like) and the build uses -Werror. Suppressed with @SuppressWarnings("module") + a comment — it mirrors the Sonatype-verified io.github.dfa1 namespace and the package name, so diverging would be worse.
  • Cross-module native resource. With a module descriptor, the zstd module runs on the module path, where Class#getResourceAsStream only sees its own module — so the bundled libzstd (in a separate zstd-native-<classifier> jar) wasn't found and every test failed with UnsatisfiedLinkError. Fixed by loading through the class loader (no leading slash); the classifier directory name has a dash, so the resource isn't in a package and isn't module-encapsulated → readable across modules and on the classpath alike.

Retest

./mvnw verify (full reactor) — all unit + 79 integration tests green, checkstyle + javadoc clean across all 12 modules. Native library loads on the module path.

Known benign warning: the benchmark JMH uber-jar shade reports "Discovered module-info.class. Shading will break its strong encapsulation" — harmless for the non-published benchmark harness.

🤖 Generated with Claude Code

- module-info.java exports the single public package. Lets modular
  consumers `requires io.github.dfa1.zstd` and scope native access with
  `--enable-native-access=io.github.dfa1.zstd` instead of ALL-UNNAMED.
- Suppress the module-name lint: the `dfa1` component ends in a digit
  (flagged as possibly version-like), but it mirrors the verified
  io.github.dfa1 namespace and the package, so keep it.
- NativeLibrary now loads the bundled library through the class loader
  (no leading slash) rather than Class#getResourceAsStream: the library
  lives in a separate zstd-native-<classifier> module and a named module
  only finds resources in itself. The classifier directory has a dash, so
  it is not a package and the resource is not module-encapsulated — the
  class loader reads it across modules and on the classpath alike.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dfa1 dfa1 force-pushed the feat/jpms-module-info branch from 8c58ecb to aae6cbf Compare July 12, 2026 15:52
… ADR 0011

CHANGELOG.md — 0.8 Added entry for the module-info.java change.
docs/reference.md — spell out the module-path native-access flag
(--enable-native-access=io.github.dfa1.zstd) and add a Module path
section describing the export surface and classpath fallback.
adr/0011-jpms-module-descriptor.md, adr/ADR.md — flip status
Proposed -> Accepted now that the descriptor is implemented.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@dfa1 dfa1 merged commit 513c677 into main Jul 12, 2026
1 check passed
@dfa1 dfa1 deleted the feat/jpms-module-info branch July 12, 2026 16:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant