A reference project that shows how to call Open Enclave enclaves from a Java application through a JNI bridge. It bundles a sample enclave, host-side glue, and a Gradle-based app so you can experiment end-to-end with ECALL/OCALL flows from the JVM.
-
Generate JNI headers with Gradle (required before the C++ build):
./gradlew compileJava
-
Configure CMake and build the native artifacts (enclave + JNI host library):
cmake --preset default cmake --build --preset default
This produces
build/lib/liboe_jni.{so|dylib|dll}and signs the sample enclave intobuild/artifacts/enclaves/example/example.signed. -
Update
app/src/main/java/org/oejava/example/App.javaso the hard-coded path passed toExampleEnclave.create()points at the signed enclave generated above, then run the Java sample:./gradlew run
Gradle sets
java.library.pathtobuild/lib, so the JVM picks upliboe_jniautomatically. Use the--simulateflag when building/running the native host if you do not have SGX hardware available.
app/– Gradle project with the Java example (App) and the JNI stub class (ExampleEnclave).enclaves/example/– The sample enclave (EDL file, trusted implementation, signing config).host/– JNI bridge (jni_bridge.cpp), OCALL implementations, and an optional CLI host (host.cpp).cmake/OEEnclave.cmake– Helper functionadd_oe_enclave()that drivesoeedger8r, enclave compilation, and signing.scripts/– Convenience scripts, includingcheck_sgx.sh(hardware capability probe) and devcontainer helpers..devcontainer/– Docker setup for a reproducible development environment with OE, JDK 21, CMake, and tooling pre-installed.
Generated output lives under build/ (CMake) and app/build/ (Gradle).
- Open Enclave SDK 0.19.x or newer (provides
oeedger8r,oehost,oesign, headers, and libraries). - CMake ≥ 3.20, Clang/LLVM ≥ 11, and
ninjaor Make (the presets use Unix Makefiles by default). - JDK 21 (managed automatically if you rely on the Gradle toolchain) and Gradle wrapper (
./gradlew). - SGX2-capable hardware + drivers for a hardware-backed run, or use OE's simulation mode.
- Optional: Docker if you prefer the supplied devcontainer (
scripts/devcontainer-*.sh).
Check SGX support quickly with:
scripts/check_sgx.sh-
./gradlew compileJavaemits JNI headers underbuild/generated/jni/. Rerun this whenever you changeExampleEnclave.java. -
cmake --preset defaultconfigures the project withBUILD_JNI_HOST=ONandBUILD_HOST_EXE=OFF. -
cmake --build --preset defaultcompiles the enclave, generates all EDL stubs, buildsliboe_jni, and signs the enclave. Usecmake --build --preset default --target sign_allif you only need to re-sign after editing.conffiles. -
Enable the tiny CLI host for debugging by configuring with the
testpreset or passing-DBUILD_HOST_EXE=ON, then run it against the signed enclave:cmake --preset test cmake --build --preset test --target oe_cli ./build/bin/oe_cli --simulate build/artifacts/enclaves/example/example.signed
Omit
--simulatewhen running on hardware with SGX enabled.
-
After wiring the enclave path,
./gradlew runlaunchesorg.oejava.example.App, which creates the enclave, performs thehelloworldECALL, and tears it down. -
Unit tests (currently a placeholder) run via:
./gradlew test -
If you run outside Gradle, set
java.library.path(orLD_LIBRARY_PATH/DYLD_LIBRARY_PATH) so the JVM can loadliboe_jni, and make sure the signed enclave is accessible to the host process.
-
Edit
.devcontainer.env(create it if needed) and setSSH_PUBKEYto the public key you want inside the container. -
Bring the container up:
./scripts/devcontainer-up.sh
The image ships with the Open Enclave SDK, JDK 21, CMake, Neovim, and other tooling. Additional helpers in
scripts/can attach, stop, or tear down the container.
- When adding new enclaves, create a directory under
enclaves/and calladd_oe_enclave()in itsCMakeLists.txt; the helper aggregates all generated untrusted stubs for the host. - JNI signatures live in
build/generated/jni. Keep Gradle and CMake builds in sync so regenerated headers are picked up. - Use OE's simulation mode (
OE_ENCLAVE_FLAG_SIMULATE) while iterating on machines without SGX, then rebuild withdebug=falsefor production. - Clean builds with
rm -rf build app/buildor invokecmake --build --preset default --target cleanand./gradlew clean.