ENGLISH | 中文
Java bindings for Godot.
Built on top of GDExtension and Panama FFI to make Java a first-class citizen in the Godot ecosystem.
Status: 0.1.0 – production-ready with scoped memory management and full GDExtension feature coverage.
Project examples:
In the game engine world, Java is almost always the missing language:
Meanwhile, Java remains one of the most widely used languages on the planet — dominant in enterprise backends, Android development, and large-scale data processing. Millions of developers write Java every day, yet the game engine ecosystem offers them almost nothing.
For teams with an existing Java stack, this is a real gap:
godot-java aims to challenge the “no Java in game development” status quo:
From an engineering point of view, the goals are:
This project deliberately targets Java 25+ instead of trying to support older LTS releases like 8/11/17.
There are three main reasons:
No legacy baggage
By focusing on a single modern Java version, we keep the codebase clean and straightforward.
There is no need to carry around compatibility layers or branching logic for older JDKs.
Use the latest language and platform features
We can freely use:
switch expression and var where it makes sensejava.lang.foreign Panama FFI APIsLet you fully enjoy modern Java
The idea is to let you write game code while enjoying everything modern Java has to offer:
If you are curious what “Godot + modern Java + Panama FFI” can look like, this project is meant as a clean, modern starting point rather than a legacy SDK that evolved from older Java versions.
Core capabilities currently implemented:
Godot GDExtension binding (C API)
GDExtensionInterfaceGetProcAddress to dynamically load the Godot APIGDExtensionClassLibraryPtr, GDExtensionPropertyInfo, GDExtensionClassMethodInfo, etc.Java 25 Panama FFI integration
java.lang.foreign (Linker, FunctionDescriptor, MemorySegment, …) to call into GodotAnnotation-driven class / method / property / signal registration
@GodotClass – declare a Java class that can be instantiated from Godot@GodotMethod – expose a Java method to be called from Godot@Export – export a field to the Godot Inspector with hint/hintString support@Signal – declare and emit Godot signals from Javagodot-java-processor) generates typed dispatch code at compile time (zero runtime reflection in the hot path)APT-compiled typed dispatch (aligned with gdext/Rust architecture)
TypedDispatch_<ClassName> — MethodHandle/VarHandle-based method dispatchPropertyAccess_<ClassName> — VarHandle-based property access for @Export fieldsVirtualDispatch_<ParentClass> — per-parent-class hash maps for virtual method resolutionVirtual methods and lifecycle callbacks
get_virtual_func upcall stubs (lazy, only for overridden methods)notification_func, to_string_func, reference_func/unreference_func, validate_property_funcptrcall support
ref_get_object/ref_set_object for RefPtr parametersProperty system
get_property_list_func — exposes @Export fields to Godot editorproperty_can_revert_func/property_get_revert_func — default value supportType system and Variant interop
Variant, GodotStringName, GodotString, GodotArray, GodotDictionary, etc.The dispatch architecture is aligned with gdext (the Rust bindings): upcall stubs are created lazily at class registration time, only for methods the user actually overrides. Unimplemented methods return NULL so Godot uses its default C++ implementation.
The annotation processor (godot-java-processor) generates per-class dispatch code at compile time:
TypedDispatch_<ClassName> — MethodHandle/VarHandle-based method dispatch (zero reflection on the hot path)PropertyAccess_<ClassName> — VarHandle-based property access for @Export fieldsVirtualDispatch_<ParentClass> — per-parent-class hash maps for virtual method resolution (reduces candidate names from 1000+ to ~12)get_virtual_func upcall stubs — lazy, only created for methods the user actually overridesMethodHandle pre-cached dispatch with reflection fallbackStringName pointer comparisonnotification_func — forwards Godot notifications to onNotification(int) on the Java instanceto_string_func — bridges Java toString() to Godot's string representationreference_func / unreference_func — atomic reference counting for RefCounted-derived classesvalidate_property_func — property validation pass-through for editor integrationVariant boxing overhead for method callsref_get_object/ref_set_object for RefPtr parametersMethodHandle dispatch for registered @GodotMethod methods@Export annotation with hint and hintString for Godot editor integrationget_property_list_func — exposes @Export fields to the Godot Inspectorproperty_can_revert_func / property_get_revert_func — default value support for revert behavior@Signal annotation for signal declaration and emission from JavaSome key technical choices in this project:
GDExtension (Godot 4 official extension mechanism)
.dylib / .so / .dll)Java 25 Panama FFI
java.lang.foreign)FunctionDescriptor / MemoryLayoutAnnotation-based registration model
There are several ways to bring other languages into Godot. Here is how godot-java compares to the main alternatives:
| Integration | FFI | Virtual methods | ptrcall | Barrier to entry | Maturity | |
|---|---|---|---|---|---|---|
| godot-java | GDExtension | Panama FFI (Java 25) | All 1144 | Supported | Low (no engine recompile) | Alpha |
| godot-rust/gdext | GDExtension | Rust FFI | All supported | Supported | Low (no engine recompile) | Stable |
| graphics.gd (Go) | GDExtension | CGO | Supported | — | Low (no engine recompile) | Community |
| godot-kotlin-jvm | Engine module | JNI | All supported | Supported | High (requires recompiling Godot) | Stable |
| C# (official) | Engine module | N/A | All supported | Supported | Medium (Mono embedded) | Official |
The fundamental difference is how a language integrates with Godot:
GDExtension is Godot 4's official plugin API. Languages built on it compile to a shared library (.so/.dylib/.dll) that Godot loads at runtime. No engine recompilation is needed — users download a standard Godot binary and load the extension. This is the path taken by godot-java, gdext, and graphics.gd.
Engine module compiles the language directly into the Godot C++ process. This gives full access to everything the engine offers (all virtual methods, Input.*, etc.) but requires recompiling the entire Godot engine from source. This is the path taken by godot-kotlin-jvm (due to JVM embedding requirements) and C# (Godot's built-in option).
godot-java follows the GDExtension path. It supports all 1144 virtual methods across all Godot classes, auto-scanned from extension_api.json. The dispatch architecture is aligned with gdext (Rust bindings): upcall stubs are created lazily at class registration time, only for methods the user actually overrides. Unimplemented methods return NULL so Godot uses its default C++ implementation.
If you are coming from gdext: godot-java aims for a similar architecture, with Java instead of Rust and Panama FFI instead of native Rust FFI.
There are two documentation tracks: English and Chinese.
docs/README.md
Under docs/en/:
docs/en/user/getting-started.md — Requirements, build, loading the extension in Godotdocs/en/user/api.md — API overview and common typesdocs/en/user/guide.md — Usage guide and best practicesdocs/en/user/troubleshooting.md — Common issues and debugging tipsdocs/en/dev/architecture.md — Internal architecture (GDExtension + FFI)docs/en/dev/building.md — Build, packaging, and upgrading Godot versiondocs/en/dev/contributing.md — How to contributedocs/en/dev/debugging.md — Debugging Godot/Java integrationgodot-java/
├── pom.xml # Root Maven project (aggregator)
├── godot-api/ # Godot API JSON files (input to code generator)
│ ├── extension_api.json # Godot class/method/property definitions
│ ├── gdextension_interface.json # GDExtension C interface definitions
│ └── gdextension_interface.h # GDExtension C header (reference)
├── godot-java-core/ # Core runtime and Godot Java bindings
│ ├── native/src/godot_java.cpp # C++ entry point (GDExtension initialization)
│ ├── src/main/java/org/godot/
│ │ ├── annotation/ # @GodotClass, @GodotMethod, @Export, @Signal
│ │ ├── bootstrap/ # JVM startup & GDExtension entry
│ │ ├── bridge/ # Panama FFI bridge (VirtualDispatch, InstanceCallbacks)
│ │ ├── core/ # Variant, StringName, GodotString, Callable…
│ │ ├── collection/ # GodotArray, GodotDictionary
│ │ ├── math/ # Vector2/Vector3, Transform2D/3D…
│ │ ├── node/ # 1016 generated node wrappers (Node, Node2D, Control…)
│ │ ├── internal/api/ # Auto-generated: ApiIndex, ApiSignatures, VariantType, VirtualMethods…
│ │ └── registration/ # Annotation scanning & class registration
│ └── src/test/java/ # Unit tests
├── godot-java-code-generator/ # Code generator (from Godot API JSON)
│ └── src/main/java/com/godot/codegen/
│ ├── Main.java # Entry point
│ ├── ApiIndexGenerator.java # 176 API function indices
│ ├── ApiSignaturesGenerator.java # Panama FunctionDescriptors
│ ├── VariantTypeGenerator.java # Variant type enum
│ ├── VirtualMethodGenerator.java # Virtual method metadata
│ ├── ClassGenerator.java # 1016 node wrapper classes
│ └── StructLayoutComputer.java # C struct offset calculator
├── godot-java-processor/ # APT annotation processor
│ └── src/main/java/org/godot/processor/
│ └── GodotClassProcessor.java # Generates TypedDispatch/VirtualDispatch at compile time
├── godot-java-examples/ # Example projects (10 examples)
│ ├── src/main/java/examples/ # Java source (helloworld, pong, snake…)
│ └── examples/01-*/~10-*/ # Godot projects with .tscn, .gd, native/
├── upgrade-godot-api.sh # One-command Godot version upgrade
└── docs/ # Documentation (EN + ZH)
├── en/user/ | en/dev/
└── zh/user/ | zh/dev/
When Godot releases a new version, godot-java can be upgraded in one step:
./upgrade-godot-api.sh 4.7
This script:
extension_api.json and gdextension_interface.json from godot-cppThen verify:
./mvnw clean install -DskipTests
To get a demo running:
Make sure you have:
Read:
Then:
godot-java-core and godot-java-code-generator@GodotClass-annotated Java script and experimentContributions are very welcome:
See: docs/en/dev/contribution.md