A Java code-generation library that bridges C/C++ native code to JVM platforms -- desktop, mobile, and web.
- Overview
- How It Works
- Supported Targets
- Code Block Convention
- WebIDL Bindings
- IDLBase API
- Requirements
- Documentation
- Getting Started
- Libraries Using jParser
- License
Inspired by gdx-jnigen, jParser lets you embed native C/C++ code directly inside Java source files using annotated comment blocks. Each block is translated into target-specific Java source code, enabling a single base module to produce a bridge-agnostic core API plus platform bridge outputs for JNI (desktop/mobile), FFM (desktop, Java 25+), and TeaVM (web via JS/WASM).
For web targets, jParser uses Emscripten to compile C/C++ into JS/WASM and TeaVM to generate the corresponding Java-to-JavaScript bridge via @JSBody annotations.
jParser consists of two main stages:
Reads the hand-written Java source in the base module, which contains embedded native code blocks, and generates platform-specific Java source for each target:
| Output Module | Target | Description |
|---|---|---|
core |
Core API | Generated bridge-agnostic API classes |
shared/<Lib>-jni |
JNI | Generated JNI Java shared by desktop and Android |
shared/<Lib>-c |
TeaVM C | Generated TeaVM C Java shared by desktop and Android |
desktop/<Lib>-desktop-ffm |
FFM | Generated FFM Java for desktop (Java 25+) |
web/<Lib>-web |
TeaVM web | Generated @JSBody-annotated Java for web |
android/<Lib>-android |
JNI (Android) | Android JNI packaging |
android/<Lib>-android-c |
TeaVM C (Android) | Android TeaVM C packaging |
Compiles the C/C++ source into platform-specific native libraries:
| Platform | Toolchain |
|---|---|
| Windows | MSVC |
| Linux | GCC / G++ |
| macOS | Xcode CLI tools |
| Android | Android NDK |
| Web | Emscripten SDK |
| Target | Bridge | Platforms | Java Version |
|---|---|---|---|
| JNI | Java Native Interface | Windows, Linux, macOS, Android | 8+ |
| FFM | Foreign Function & Memory API | Windows, Linux, macOS | 22+ |
| TeaVM | JavaScript / WASM | Web browsers | Java 17+ for TeaVM 0.15 web modules/tooling |
In base Java source files, native code is embedded via annotated comment blocks. jParser reads these blocks and generates the appropriate code for each target.
public class MyLib extends IDLBase {
// TeaVM replacement — generates @JSBody-annotated method for web
/*[-TEAVM;-REPLACE]
@org.teavm.jso.JSBody(params = {"this_addr"},
script = "var jsObj = [MODULE].wrapPointer(this_addr, [MODULE].MyType);"
+ "return jsObj.getValue();")
private static native int internal_native_getValue(int this_addr);
*/
// JNI native code block — compiled into C++ for desktop & mobile
/*[-JNI;-NATIVE]
MyType* obj = (MyType*)this_addr;
return obj->getValue();
*/
private static native int internal_native_getValue(long this_addr);
}| Command | Description |
|---|---|
-NATIVE |
Inline C/C++ code compiled for the target |
-ADD |
Adds code to the generated output |
-ADD_RAW |
Adds raw code without processing |
-REMOVE |
Removes code from the generated output |
-REPLACE |
Replaces the following method with the block content |
-REPLACE_BLOCK |
Replaces the following code block |
-IDL_SKIP |
Placed on a class comment to skip IDL generation for that class |
To reduce the effort of manually porting each method, jParser supports Emscripten WebIDL. Define a .idl file and jParser automatically generates binding code for all targets.
interface NormalClass {
void NormalClass();
long addIntValue(long value1, long value2);
static long subIntValue(long value1, long value2);
attribute long intValue;
attribute float floatValue;
};This generates fully working Java classes with native bindings for JNI, FFM, and TeaVM — no manual glue code required.
- IDL helper classes (
IDLInt,IDLIntArray, etc.) let you pass primitive pointers to C++. They work across Emscripten, desktop, and mobile. - C++ enums are converted into Java enums, each carrying the integer value from native code.
[Value]methods return a cached copy of the object. The cache is overwritten on each call — do not retain references.[NoDelete]classes should not havedispose()called. All other classes require explicit disposal.
Every native class extends IDLBase, which provides common memory-management functionality.
Important: jParser does not automatically dispose C++ objects. You must call
dispose()when you're done with an object to free native memory. Only objects you create or explicitly own require disposal. Creating and disposing native objects is expensive — avoid doing it every frame.
| Method | Description |
|---|---|
ClassName.native_new() |
Creates an empty instance without native data |
ClassName.NULL |
Returns a NULL instance — use instead of Java null for native parameters |
dispose() |
Deletes the native instance (only if owned) |
isDisposed() |
Checks whether the native instance has been disposed |
native_setVoid(...) |
Sets an integer or long memory address |
native_reset() |
Resets the instance to default state |
native_takeOwnership() |
Takes ownership, enabling dispose() to delete the object |
native_releaseOwnership() |
Releases ownership, preventing dispose() from deleting |
native_hasOwnership() |
Checks whether you own the native instance |
native_copy(...) |
Copies memory address and native data from another instance |
The
native_prefix is used to avoid naming conflicts with C/C++ methods.
| Requirement | Purpose |
|---|---|
| JDK 11+ | Building jParser tool modules |
| JDK 22+ (25 recommended) | FFM modules and FFM-based apps |
| Visual Studio C++ | Windows native builds |
| GCC / G++ | Linux native builds |
| Xcode CLI tools | macOS native builds |
| Emscripten SDK | Web builds (JS/WASM) |
Windows (MSVC): Windows native builds initialize the Visual Studio C++ environment with
vcvarsall.bat. The build auto-detects it fromVCVARSALL_PATH/JPARSER_VCVARSALL,PATH, Visual Studio environment variables, orvswhere.exe. To force a location, pass-Djparser.vcvarsall=C:\Program Files\Microsoft Visual Studio\[Year]\[Edition]\VC\Auxiliary\Build\vcvarsall.bat.
- Runtime publishing/classifier strategy guide:
docs/runtime-maven-artifacts.md - Architecture details:
docs/architecture.md - Workflow/checklists:
docs/workflows.md - Command matrix:
docs/commands.md
For a complete working example, refer to the examples/TestLib module.
jParser projects follow a module pattern centered on source (base), generator entry (builder), and generated/runtime-specific outputs:
| Module Suffix | Purpose |
|---|---|
base |
Hand-written Java source with embedded native code blocks |
builder |
Build entry point that configures IDL, targets, generation, and native compilation |
core |
Generated bridge-agnostic API output (do not hand-edit) |
shared/<Lib>-jni |
Generated JNI Java shared by desktop and Android JNI (do not hand-edit) |
shared/<Lib>-c |
Generated TeaVM C Java shared by desktop and Android C (do not hand-edit) |
desktop/<Lib>-desktop-jni |
Desktop JNI native payloads |
desktop/<Lib>-desktop-ffm |
Generated desktop FFM Java output + native payloads (do not hand-edit) |
desktop/<Lib>-desktop-c |
Desktop TeaVM C native payloads |
web/<Lib>-web |
Generated TeaVM WebAssembly output (do not hand-edit) |
android/<Lib>-android |
Android JNI packaging |
android/<Lib>-android-c |
Android TeaVM C packaging |
# 1. Build runtime (required once)
./gradlew :jParser:runtime:builder:runtime_helper_build_project_windows64_jni
./gradlew :jParser:runtime:builder:runtime_helper_build_project_windows64_ffm
# 2. Generate code + compile native library
./gradlew :examples:TestLib:lib:builder:TestLib_build_project_windows64_jni
./gradlew :examples:TestLib:lib:builder:TestLib_build_project_windows64_ffm
# 3. Run the desktop app
./gradlew :examples:TestLib:app:platforms:desktop-jni:TestLib_run_app_desktop_jni
./gradlew :examples:TestLib:app:platforms:desktop-ffm:TestLib_run_app_desktop_ffm
Replace
windows64withlinux64,mac64, ormacArmfor other platforms. On Windows, usegradlew.batinstead of./gradlew. Desktop FFM app tasks useLibExt.javaFFMTarget; ensure that Java toolchain is available when running..._run_app_desktop_ffmtasks.
| Library | Description | Status |
|---|---|---|
| jWebGPU | WebGPU bindings for Java | Active |
| xImGui | Dear ImGui bindings for Java | Active |
| xJolt | Jolt Physics bindings for Java | Active |
| xLua | Lua bindings for Java | Active |
| xBullet | Bullet Physics bindings for Java | Active |
| gdx-box2d | Box2D bindings for libGDX | Inactive |
| gdx-physx | PhysX bindings for libGDX | Inactive |
If you find this project valuable and want to fuel its continued growth, please consider sponsoring it. Your support keeps the momentum going!
jParser is licensed under the Apache License 2.0.