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: production-ready with scoped memory management, full GDExtension feature coverage, and Maven Central desktop runtime artifacts.
For application development, start from the standalone godot-java-template project. Do not clone this framework repository as the base for a game.
git clone https://github.com/youngledo/godot-java-template.git my-godot-game
cd my-godot-game
./mvnw package
./mvnw verify -Pgodot-runThe template is the supported desktop project layout. It consumes released
Maven artifacts, builds your Java code into target/app.jar, resolves the
matching godot-java-native artifact, and syncs both into the Godot project
under godot/godot-java/.
Useful template commands:
./mvnw package— build Java and syncapp.jarplus the native library./mvnw verify -Pgodot-run— build, sync, then launch Godot for this project./mvnw verify -Pgodot-doctor— diagnose JDK,.gdextension, jar, registry, and native layout
Use this repository directly when contributing to the binding itself, running framework tests, or studying the internal examples.
Demo and example projects:
- godot-java-examples — 10 small examples in this repo
- godot-java-demo-projects — 107 official Godot demos ported to Java (2D, 3D, audio, GUI, networking, XR, and more)
- godot-java-3d-demo — a 3D character demo
In the game engine world, Java is almost always the missing language:
- Unity offers C# as its scripting language — no Java
- Unreal Engine is firmly C++ — no Java
- Godot ships with GDScript and C# — no Java
- Even community-maintained bindings (e.g. godot-kotlin-jvm) target Kotlin or require recompiling the engine
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:
- Their codebase, tools, and engineering practices are all built around Java
- Trying a game engine often means:
- Learning and maintaining a completely different language (C++/GDScript/C#), or
- Building and maintaining a fragile bridge between Java and the engine
godot-java aims to challenge the “no Java in game development” status quo:
- Give Java a first-class seat in the Godot ecosystem
- Let existing Java teams reuse:
- Their language and IDEs (IntelliJ IDEA / Eclipse / VS Code, etc.)
- Their build and dependency tooling (Maven/Gradle)
- Their testing, logging, diagnostics, and CI/CD pipelines
From an engineering point of view, the goals are:
- Provide a natural Java experience (annotations, strong typing, modern FFI)
- Avoid piles of custom JNI glue – lean on Java 25’s Panama FFI instead
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:- Records, sealed types, pattern matching
- The enhanced
switchexpression andvarwhere it makes sense - The latest
java.lang.foreignPanama FFI APIs
This allows the binding code itself to look and feel like modern Java, not “Java written as if it were C”.
Let you fully enjoy modern Java
The idea is to let you write game code while enjoying everything modern Java has to offer:- Expressive language features
- A rich library ecosystem
- A familiar toolchain
Without constantly worrying “will this feature work on some old JDK?”
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)
- Uses
GDExtensionInterfaceGetProcAddressto dynamically load the Godot API - Models core C structs such as
GDExtensionClassLibraryPtr,GDExtensionPropertyInfo,GDExtensionClassMethodInfo, etc.
- Uses
Java 25 Panama FFI integration
- Uses
java.lang.foreign(Linker,FunctionDescriptor,MemorySegment, …) to call into Godot - No custom JNI-based helper library is required
- Uses
Annotation-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 withhint/hintStringsupport@ExportGroup/@ExportSubgroup– organize exported properties in the Inspector@Signal– declare and emit Godot signals from Java with type-safeTypedSignal0-5- APT processor (
godot-java-processor) generates the required typed dispatch metadata at compile time; runtime dispatch does not use reflection
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 resolution- APT-generated metadata is required; missing metadata causes initialization or dispatch failure rather than a reflection fallback
Virtual methods and lifecycle callbacks
- Supports all 1144 virtual methods across all Godot classes
- Per-class
get_virtual_funcupcall stubs (lazy, only for overridden methods) - Lifecycle callbacks:
notification_func,to_string_func,reference_func/unreference_func,validate_property_func
ptrcall support
- Zero-copy typed pointer dispatch (avoids Variant boxing for method calls)
- RefCounted-aware: uses
ref_get_object/ref_set_objectfor RefPtr parameters - APT-generated MethodHandle dispatch for registered @GodotMethod methods
Property system
get_property_list_func— exposes @Export fields to Godot editorproperty_can_revert_func/property_get_revert_func— default value support- Hash collision resolution by StringName pointer comparison
Type system and Variant interop
- Java-side types for
Variant,GodotStringName,GodotString,GodotArray,GodotDictionary, etc. - Safe conversions between common Java types and Godot Variants
- Enum/Bitfield types — method parameters and returns use Java enums instead of raw
int/long(e.g.DisplayServer.WindowMode,WebSocketPeer.State) - Typed signals —
TypedSignal0throughTypedSignal5for compile-time arity-checked signal emission Godot.instantiate()— type-safe scene instantiation API
- Java-side types for
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@ExportfieldsVirtualDispatch_<ParentClass>— per-parent-class hash maps for virtual method resolution (reduces candidate names from 1000+ to ~12)- Requires APT-generated metadata; there is no runtime reflection fallback
- Per-class
get_virtual_funcupcall stubs — lazy, only created for methods the user actually overrides - APT-generated per-parent-class hash resolution — eliminates false matches across unrelated classes sharing method names
MethodHandlepre-cached dispatch without a reflection fallback- Hash collision resolution by
StringNamepointer comparison
notification_func— forwards Godot notifications toonNotification(int)on the Java instanceto_string_func— bridges JavatoString()to Godot's string representationreference_func/unreference_func— atomic reference counting forRefCounted-derived classesvalidate_property_func— property validation pass-through for editor integration
- Zero-copy typed pointer dispatch — avoids
Variantboxing overhead for method calls - RefCounted-aware — uses
ref_get_object/ref_set_objectforRefPtrparameters - APT-generated
MethodHandledispatch for registered@GodotMethodmethods
@Exportannotation withhintandhintStringfor Godot editor integration@ExportGroup/@ExportSubgroup— organize properties into named groups in the Inspectorget_property_list_func— exposes@Exportfields to the Godot Inspectorproperty_can_revert_func/property_get_revert_func— default value support for revert behavior@Signalannotation withTypedSignalfor type-safe signal declaration and emission
Some key technical choices in this project:
GDExtension (Godot 4 official extension mechanism)
- No reliance on legacy GDNative/JNI plugin approaches
- Aligned with Godot’s loading and lifecycle model
- Distributed as a shared library (
.dylib / .so / .dll)
Java 25 Panama FFI
- Uses the standard FFI API in the JDK (
java.lang.foreign) - Function signatures and memory layouts are modeled via
FunctionDescriptor/MemoryLayout - Easier to navigate and refactor in IDEs
- Uses the standard FFI API in the JDK (
Annotation-based registration model
- Generates the registration data Godot needs from annotations at compile time
- Avoids writing repetitive registration code on the C/C++ side
- Feels more like writing a normal Java application
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 | 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.
- Index:
docs/README.md- Explains the documentation structure
- Helps you find the right language / role-specific docs
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 integration
godot-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/ # 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 # 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.7This script:
- Downloads the new
extension_api.jsonandgdextension_interface.jsonfrom godot-cpp - Re-runs the code generator, which auto-updates:
- ApiIndex.java — API function indices
- ApiSignatures.java — Panama FunctionDescriptor for each function
- VariantType.java — Variant type enum
- StructOffsets.java — C struct field offsets
- VirtualMethods.java — virtual method metadata (1144 methods, name→hash lookup)
- ObjectMethodHashes.java — method bind hashes for Object
- 1016 node wrapper classes — engine type API changes
Then verify:
./mvnw clean install -DskipTestsRead docs/en/user/getting-started.md for the full template workflow, Maven coordinates, and manual integration notes.
Contributions are very welcome:
- Bug reports, design discussions, and UX feedback
- Documentation improvements
- Platform / Godot version compatibility testing
- Expanding API coverage and tests
See: docs/en/dev/contribution.md
- The Godot Engine team and community for an open, powerful engine and GDExtension API
- The OpenJDK Panama team for bringing modern FFI to Java
- Everyone who has tried to use Java in game development – this project is also for you.