Backend Development 12 min read

Using LuaJ to Call Java Methods from Lua and Vice Versa

This article explains the main features of LuaJ, provides usage examples for calling Java static methods from Lua (including handling signatures and return values), demonstrates how to pass Lua functions to Java, and shows how to embed and execute Lua scripts within Java code.

Top Architect
Top Architect
Top Architect
Using LuaJ to Call Java Methods from Lua and Vice Versa

In certain business scenarios you may need to call Java code from Lua. While JNI can achieve this, LuaJ (LuaJavaBridge) offers a more convenient solution.

LuaJ Main Features

Call Java class static methods from Lua.

Support five parameter types when invoking Java methods: int, float, boolean, String, and Lua function.

Pass a Lua function as a parameter to Java and let Java keep a reference to it.

Call global Lua functions from Java or invoke a referenced Lua function.

LuaJ’s functionality is simple yet fully meets the needs of integrating various SDKs.

Usage Example

Java method prototype:

public static float getNum(float n) {
    return n;
}

Lua call example:

-- Java class name
local className = "com/xttblog/Test"
-- method name
local method = 'getNum'
-- arguments
local n = 10
local args = { n }
-- call Java method
local _, testStaticMethod = luaj.callStaticMethod(className, method, args)

Implementation Principle

LuaJ’s core goals are twofold: call Java from Lua and call Lua from Java. The implementation includes:

Finding and invoking a specific Java method.

Checking the call result and retrieving the return value.

Passing a Lua function as a parameter to Java.

Calling a Lua function from Java.

Finding and Calling a Specific Java Method

JNI provides FindClass() to locate a class; the first argument of luaj.callStaticMethod() is the full class name with slashes instead of dots.

After locating the class, GetStaticMethodID() finds the static method using its name and signature. A signature describes parameter and return types, e.g., (Ljava/lang/String;ZZI)V .

LuaJ can automatically infer the signature from the provided arguments, but when inference fails you must define the signature explicitly.

Example of specifying a signature:

public static int getNum(int n) {
    return n;
}
-- Java class name
local className = "com/xttblog/Test"
-- method name
local method = 'getNum'
-- arguments
local n = 10
local args = { n }
-- define signature
local sig = "(I)I"
-- call Java method
local _, testStaticMethod = luaj.callStaticMethod(className, method, args, sig)

Signature format is (parameter types)return type . Some examples:

()V               // no parameters, void return
(I)V              // int parameter, void return
(Ljava/lang/String;)Z // String parameter, boolean return
(IF)Ljava/lang/String; // int and float parameters, String return

Type mappings:

I  -> int (or Lua function reference)
F  -> float
Z  -> boolean
Ljava/lang/String; -> String
V  -> void

Getting Return Values from Java Methods

LuaJ checks the call result and returns two values: a boolean indicating success and either the Java method’s return value or an error code.

public static int AddTwoNumbers(final int number1, final int number2) {
    return number1 + number2;
}

local args = {2, 3}
local sig = "(II)I"
local ok, ret = luaj.callStaticMethod(className, "AddTwoNumbers", args, sig)
if not ok then
    print("luaj error:", ret)
else
    print("ret:", ret) -- prints ret: 5
end

Error codes:

-1  Unsupported parameter or return type
-2  Invalid signature
-3  Method not found
-4  Exception thrown during Java method execution
-5  JVM error
-6  JVM error

Passing a Lua Function as a Parameter to Java

Lua functions are stored in a reference table and identified by an integer ID. Java methods that receive a Lua function must declare the parameter as int .

public static int getNum(int n) {
    return n;
}

local function callback(result)
    -- method content
end
local className = "com/xttblog/Test"
local method = 'getNum'
local args = { callback }
local sig = "(I)I"
local _, testStaticMethod = luaj.callStaticMethod(className, method, args, sig)

Embedding Lua Scripts in Java

You can embed Lua code as a string and execute it with LuaJ:

String luaStr = "print 'hello,world!'";
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load(luaStr);
chunk.call();

Or load a Lua script file (e.g., login.lua ) and call its functions:

-- login.lua content
function hello()
    print 'hello'
end
function test(str)
    print('data from java is:'..str)
    return 'haha'
end

// Java side
String luaPath = "res/lua/login.lua"; // script path
Globals globals = JsePlatform.standardGlobals();
globals.loadfile(luaPath).call();
LuaValue func = globals.get(LuaValue.valueOf("hello"));
func.call();
LuaValue func1 = globals.get(LuaValue.valueOf("test"));
String data = func1.call(LuaValue.valueOf("I'am from Java!")).toString();
Logger.info("data return from lua is:" + data);

Running the above prints:

hello
 data from java is:I'am from Java!

The article concludes with an invitation for readers to discuss, ask questions, and join the architecture community.

backendJavaluaJNIbridgeLuaJ
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.