---
name: luaj
description: How to interact with LuaJ (a Lua 5.2/5.3 VM on Java) from Lua scripts. Covers the luajava library: bindClass, newInstance, createClass (creating Java subclasses from Lua), self.super, instanceof, cast, createProxy, loadLib, type coercion, fields and method calls. Use when writing or debugging Lua scripts that call into Java, or when a user asks about luajava, createClass, extending Java classes from Lua, instanceof/cast in LuaJ.
---

# LuaJ — using it from Lua scripts

LuaJ is a Lua 5.2/5.3 VM implemented in Java. Lua scripts run through the `JsePlatform.standardGlobals()` environment, which includes the **`luajava`** library for binding and calling Java code. This skill covers only the Lua-script side of LuaJ: what a script can do with Java objects and classes.

## Loading and the environment

- `JsePlatform.standardGlobals()` returns a `Globals` with all standard libraries plus `luajava`.
- Scripts are loaded with `globals.load(script, "name")` and executed with `.call()`.
- Values crossing the Lua/Java boundary are coerced automatically (see Coercion below).

## The `luajava` API

### `luajava.bindClass("full.ClassName")`
Returns a Lua value representing the class. Use it for static access, constants, and constructing instances.

```lua
jframe = luajava.bindClass("javax.swing.JFrame")
frame = luajava.newInstance("javax.swing.JFrame", "Texts")
frame:setSize(300, 400)
frame:setVisible(true)
```

### `luajava.newInstance("full.ClassName", ...args)`
Creates a Java instance via the matching public constructor.

### `luajava.new(obj, ...args)`
Alias that constructs an instance from an already-bound class.

### `luajava.createProxy(iface1, iface2, ..., methodsTable)`
Creates a `java.lang.reflect.Proxy` for one or more Java interfaces, dispatching interface methods to Lua functions. Unlike `createClass` it cannot extend classes.

```lua
listener = luajava.createProxy("java.awt.event.ActionListener", {
  actionPerformed = function(self, event)
    print("clicked")
  end
})
```

### `luajava.loadLib("ClassName", "methodName")`
Invokes a static, no-argument method on a class and returns its result.

### `luajava.createClass(superClassName, iface1, iface2, ..., methodsTable)`
Generates a **real Java subclass** at runtime. It extends the superclass (abstract classes allowed) and implements any number of interfaces. Overridden methods dispatch to Lua functions. Instances are genuine Java objects and can be passed to Java code expecting the superclass or interface type.

```lua
cls = luajava.createClass("org.luaj.vm2.lib.jse.TestBaseClass", {
  base_method = function(self) return "lua-base" end,
  toString   = function(self) return "lua-object" end,
})

o = cls:new("ctorArg")        -- mirrors the public constructors of the superclass
print(o:base_method())        -- "lua-base"  (Lua override)
print(o:toString())           -- "lua-object"
```

Rules and limits:
- The **first argument is the superclass**; following arguments are interfaces (any number); the **last argument is the methods table**.
- `self` inside a Lua method is the Java instance, so fields and methods work with normal luajava syntax: `self.field = "x"`, `self:someMethod()`.
- Only **non-final** methods can be overridden. Final classes, final methods, and ambiguous overloads raise a Lua error at creation time.
- Methods declared abstract but not implemented in Lua throw `AbstractMethodError` when invoked.
- Overriding an interface **default method** is not supported (raises a Lua error).
- Inherited methods that are not overridden behave as normal Java methods.

#### Super calls: `self.super`
Inside an overridden method, `self.super` refers to the parent implementation. Call it with the same arguments:

```lua
cls = luajava.createClass("org.luaj.vm2.lib.jse.TestBaseClass", {
  base_method = function(self)
    return "wrapped(" .. self.super:base_method() .. ")"
  end,
})
```

`self.super` is valid only inside a method of the generated class.

### `luajava.instanceof(value, "full.ClassName")`
Type check, returns a boolean:
- For an **instance** (object created in Lua or returned by Java): true if the object is an instance of the class.
- For a **class** (result of `bindClass`): true if that class inherits from / implements the target (assignability).

```lua
ok = luajava.instanceof(o, "org.luaj.vm2.lib.jse.TestInterface")  -- instance check
ok = luajava.instanceof(cls, "java.lang.Object")                  -- class inheritance check
```

### `luajava.cast(value, "full.ClassName")`
Explicit cast. Returns the value unchanged if it is assignable to the target type; raises a Lua error otherwise.

```lua
o2 = luajava.cast(o, "org.luaj.vm2.lib.jse.TestInterface")
ok, err = pcall(luajava.cast, o, "java.lang.String")   -- ok == false
```

## Member access on Java objects

- **Methods**: `obj:method(arg1, arg2)`. Overloads are resolved by LuaJ's coercion rules; if ambiguous, the call fails.
- **Fields**: `obj.field` get, `obj.field = value` set. Public fields only.
- **Static members** via `bindClass`: `MyClass.CONSTANT`, `MyClass:staticMethod(...)`.
- **Arrays**: accessed through the usual indexing/index-assign syntax on the Java array value.

## Coercion between Lua and Java

- **Lua → Java** (`CoerceLuaToJava`): numbers → int/long/float/double as the target parameter requires; strings → String (and coerced to numbers where a numeric parameter is expected); booleans → boolean; tables → Java interfaces/proxies where applicable; Lua userdata holding a Java object → that object.
- **Java → Lua** (`CoerceJavaToLua`): Java primitives/boxed → Lua numbers/booleans; Strings → Lua strings; other objects → a Lua userdata-like value through which methods and fields are reachable; `Class` → a class value usable with `bindClass` semantics.

Primitive-returning overridden methods coerce the Lua return value to the declared return type.

## Common patterns

```lua
-- implement an interface and hand the object to Java
cls = luajava.createClass("org.luaj.vm2.lib.jse.TestBaseClass",
                          "org.luaj.vm2.lib.jse.TestInterface", {
  interface_method = function(self, x) return "one(" .. x .. ")" end,
})
o = cls:new()
result = luajava.bindClass("org.luaj.vm2.lib.jse.TestBaseClass")
            :callInterface(o, "hi")            -- Java sees a real TestInterface

-- guard a cast
ok, err = pcall(luajava.cast, o, "java.lang.String")
if not ok then print("cast failed: " .. err) end
```

## Gotchas

- `instanceof` on a class value checks **class inheritance**, not instance-ness; `instanceof` on an instance checks that object's type.
- `createProxy` cannot extend classes or call `super`; use `createClass` for that.
- Do not rely on static casts changing method visibility: reflection dispatches on the runtime class.
- Not available on Java ME platforms (no reflection API).