Low level bindings for Luau.
There is a lot of prior art for interacting with Lua to/from Java:
- LuaJ (and its many forks)
- luajava (and its many forks)
- LuaTruffle for GraalVM
However, these solutions generally do not have strong sandboxing guarantees (or track record), or lose much of the performance benefit of Lua. Enter Luau. It has been proven at Roblox to be performant, well sandboxed, and easier to use through its introduction of progressive typing.
luau-java and the associated native libraries are all available
on maven central. All projects must depend on
the main luau artifact, as well as at least one of the platform specific natives. It is valid to depend on multiple
natives artifacts at the same time, they will not conflict.
Important
luau-java requires Java 25 or higher.
Gradle
dependencies {
implementation("dev.hollowcube:luau:${version}")
implementation("dev.hollowcube:luau-natives-${platform}:${version}")
}Maven
<dependencies>
<dependency>
<groupId>dev.hollowcube</groupId>
<artifactId>luau</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>dev.hollowcube</groupId>
<artifactId>luau-natives-${platform}</artifactId>
<version>${version}</version>
</dependency>
</dependencies>Replace ${platform} and ${version} with one of the following entries. Note that the core library version may be
different from the native library version.
| Platform | ${platform} |
${version} |
|---|---|---|
| - | - | |
| Windows (x64) | windows-x64 |
|
| Linux (x64) | linux-x64 |
|
| macOS (x64) | macos-x64 |
|
| macOS (arm64) | macos-arm64 |
Important
We publish two sets of native dependencies for each platform. Without a suffix on the version is release binaries,
with -debug corresponds to debug builds.
A hello world print from Luau would look something like the following:
public class HelloWorld {
static void main(String[] args) throws LuauCompileException {
final byte[] bytecode = LuauCompiler.DEFAULT.compile("print(\"Hello, Luau!\")");
final LuaState state = LuaState.newState();
try {
state.openLibs(); // Open all libraries
state.sandbox(); // Sandbox the global state so it cannot be edited by a script
var thread = state.newThread();
thread.sandboxThread(); // Create a mutable global env for scripts to use
thread.load("helloworld.luau", bytecode); // Load the script into the VM
thread.pcall(0, 0); // Eval the script
state.pop(1); // Pop the thread off the stack
} finally {
// Always remember to close the state when you're done with it, or you will leak memory.
state.close();
}
}
}The test sources contain library examples, which should help you to get started.
TODO: add some notes about error handling
Prerequisites: JDK 25+, CMake 3.15+, JExtract (Only required to update bindings)
git clone [email protected]:hollow-cube/luau-java.git --recurse-submodules && cd luau-java
./gradlew buildBindings are generated using JExtract. They are already included in the repository
inside of src/generated/java. They may need to be updated as Luau is updated.
./gradlew jextractContributions via PRs and issues are always welcome.
This project is licensed under the MIT License.