gpu4j
Contributing to gpu4j
Thanks for your interest in contributing! This document describes how to build, test, and submit changes.
Repository layout
The root POM aggregates two modules and is deliberately not a parent:
| module | what it is |
|---|---|
gpu4j-core | the GPU offload API; published, currently 0.4.0 |
gpu4j-sidecar | supervises a local inference server; 0.1.0-SNAPSHOT |
Neither inherits from the root, so neither picks up a version, a dependency
set or a release cycle it did not ask for. mvn verify at the root builds
and tests both.
The cost of that decision is that both module POMs spell out the versions of
the test dependencies and plugins they share, and nothing in Maven stops the
two drifting apart. ci/check-dependency-drift.sh fails the build when they
disagree; run it locally with bash ci/check-dependency-drift.sh.
The one constraint worth knowing before you move anything
CratonVM's craton-gpu4j/build.rs compiles gpu4j-core/src/main/java during
cargo build, locating it by path. Moving those sources without updating
that script is silent on this side: it degrades to an empty annotations jar
with only a cargo:warning, and the resulting VM recognises no @GpuKernel
at all.
It probes every layout this repository has had — <repo>/gpu4j-core/src/main/java,
the 2026-08-28 <repo>/craton-gpu/src/main/java, and the pre-0.3.0 flat
<repo>/src/main/java — under both the current checkout name (gpu4j) and the
old one (craton-gpu-java), plus the Windows install paths C:/craton/gpu4j,
C:/craton/gpu-java and C:/craton/craton-gpu-java. $CRATON_GPU_JAVA_SRC
overrides all of them.
The Java package names are a wire contract too. CratonVM's native-builtin
registry binds by exact string: craton/gpu/internal/Native,
craton/gpu/internal/{GpuExecutorImpl,GpuFutureImpl,GpuStreamImpl}, and
descriptors naming Lcraton/gpu/GpuExecutor;, GpuFuture, GpuStream,
GpuCallable, GpuRunnable, GpuArray, GpuKernel, EnableGpuAsync,
GpuExclude and AdmissionHint. That is why the 2026-09-06 gpu4j rename
changed the repository, the modules and the artifacts but not the packages:
renaming those needs a coordinated change in native-builtins/src/craton_gpu.rs.
Everything else — GpuBlas, Half, Transpose, PreparedKernel,
GpuDevice, and everything in craton.gpu.internal bar Native — is free to
rename.
Quick build
JDK 17 or newer is required.
mvn -q verify # both modules, tests and coverage
mvn -q -pl gpu4j-core package # just the offload API
mvn -q -pl gpu4j-sidecar package # just the sidecar
Both modules accept -Dbuild.qualifier=-something, appended to the artifact
file name. Use it when building from a worktree alongside the main checkout so
the jars cannot be confused. It is empty by default, so release output is
unchanged.
Tests
mvn test # both modules
mvn -pl gpu4j-core test # one of them
Two groups are excluded by default:
gpu— needs a real CUDA device behind a CratonVM built with--features gpu-driver, and for the sidecar, downloaded model weights. Run them with-Pgpu-tests; they self-skip via JUnit assumptions when no bridge is present.slow—HalfTest's exhaustive pass over all 2^32 floats, ~14 s. CI runs it on one matrix cell; run it locally withmvn -pl gpu4j-core test -Dsurefire.excludedGroups=gpu -Dgroups=slow.
gpu4j-core/examples/Demo.java is not under a Maven source root, so neither
command compiles it. CI does, because it drifted out of compilation once
already and shipped broken. If you change the public surface, check it:
mvn -q -DskipTests package
javac -d gpu4j-core/target/example-classes -cp gpu4j-core/target/classes gpu4j-core/examples/Demo.java
java -cp "gpu4j-core/target/classes:gpu4j-core/target/example-classes" Demo
(On Windows the classpath separator is ;, not :.)
Code coverage
mvn verify runs a JaCoCo coverage gate in both modules. The build fails
if the module bundle drops below 93% instructions / 90% lines in
gpu4j-core, or 90% instructions in gpu4j-sidecar, or if any single
class in gpu4j-core drops below 75% instructions.
The per-class rule exists because the bundle average hid the two classes that were actually thin behind a dozen at 100%: a whole feature (graph capture and replay) once landed with no tests at all and the gate did not notice.
A few classes are excluded from the gate but not from the report:
craton.gpu.internal.Native and NativeImpl are pure delegation to native
methods no stock JVM can execute, and craton.sidecar.LocalModelServer and
SidecarProcess exist to launch and supervise an OS process. Add tests for the
code you changed rather than lowering a threshold or extending that list.
Code style
- Keep changes minimal and surgical. Avoid unrelated refactors in the same PR.
- Match the existing Javadoc style on public types and methods.
- No formatter is enforced. Mirror the surrounding code's indentation and brace style.
Branch strategy
devis the integration branch;mainholds releases.- Work on a feature branch off
dev(e.g.feature/my-change,fix/issue-123). - Pull requests are squash-merged into
dev. Keep your branch focused on one logical change.
Pull request process
- Open your PR against
dev. - Link the issue it addresses (e.g.
Fixes #123). - Fill out the PR template (summary, test plan, checklist).
- Request review from a maintainer. Address feedback by pushing additional commits — the squash-merge will collapse them.
Releasing to Maven Central
Maintainers: see docs/MAVEN_CENTRAL.md for namespace setup, GPG signing, GitHub secrets, and tag-based releases.
Code of conduct
This project adheres to the Contributor Covenant Code of Conduct. By participating, you agree to abide by its terms.