`
szhnet
  • 浏览: 109456 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于在java上使用lua脚本

    博客分类:
  • java
阅读更多
Lua是一种小巧的脚本语言,现在经常被用于游戏中。

如果要在Java中使用Lua需要第三方库,如果搜索的话,一般搜到的都是LuaJava。LuaJava并不是一个纯Java的实现,它需要通过native方法调用C库,依赖于Lua 5.1。官网上可以下载到编译好的win32版LuaJava,其他平台的可以自己用源码进行编译。不幸的是它本身有一些bug,会导致JVM崩溃。而且LuaJava从2007年之后也不再更新了,没人维护。

除了LuaJava之外还有一些其他的Lua脚本引擎,比如LuaJ。LuaJ是纯Java实现的Lua解释器,没有native方法,因此相对健壮一些,不会由于一些错误轻易的导致JVM crash,而且还支持JSR-223。

现在LuaJ的release版本是2.0.3,2这个系列的版本是有线程安全问题的。我们可以写段代码来试一下。
package net.szh;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class TestLuaj {

    public static void main(String[] args) throws Exception {
        int threadCount = 4;
        final int runCount = 100000;
        ExecutorService exec = Executors.newCachedThreadPool();
        final CountDownLatch cdl = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            exec.execute(new Runnable() {

                @Override
                public void run() {
                    ScriptEngineManager mgr = new ScriptEngineManager();
                    ScriptEngine engine = mgr.getEngineByName("luaj");
                    try {
                        for (int i = 0; i < runCount; i++) {
                            engine.eval("local i = 0; assert(i)");
                        }
                    } catch (ScriptException e) {
                        e.printStackTrace();
                    } finally {
                        cdl.countDown();
                    }
                }
            });
        }
        cdl.await();
        exec.shutdown();
    }

}

执行后,有可能会出现如下的异常信息:
Exception in thread "pool-1-thread-3" java.lang.ArrayIndexOutOfBoundsException: -1
	at org.luaj.vm2.LuaThread$CallStack.onReturn(Unknown Source)
	at org.luaj.vm2.LuaClosure.execute(Unknown Source)
	at org.luaj.vm2.LuaClosure.onInvoke(Unknown Source)
	at org.luaj.vm2.LuaClosure.invoke(Unknown Source)
	at org.luaj.vm2.script.LuaScriptEngine$CompiledScriptImpl.eval(Unknown Source)
	at org.luaj.vm2.script.LuaScriptEngine.eval(Unknown Source)
	at org.luaj.vm2.script.LuaScriptEngine.eval(Unknown Source)
	at org.luaj.vm2.script.LuaScriptEngine.eval(Unknown Source)
	at net.szh.TestLuaj$1.run(TestLuaj.java:27)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
	at java.lang.Thread.run(Thread.java:662)

官方的jar包没把行号编译进去,我们可以自己打个jar包。
Exception in thread "pool-1-thread-3" java.lang.ArrayIndexOutOfBoundsException: -1
	at org.luaj.vm2.LuaThread$CallStack.onReturn(LuaThread.java:345)
	at org.luaj.vm2.LuaClosure.execute(LuaClosure.java:506)
	at org.luaj.vm2.LuaClosure.onInvoke(LuaClosure.java:176)
	at org.luaj.vm2.LuaClosure.invoke(LuaClosure.java:168)
	at org.luaj.vm2.script.LuaScriptEngine$CompiledScriptImpl.eval(LuaScriptEngine.java:207)
	at org.luaj.vm2.script.LuaScriptEngine.eval(LuaScriptEngine.java:111)
	at org.luaj.vm2.script.LuaScriptEngine.eval(LuaScriptEngine.java:107)
	at org.luaj.vm2.script.LuaScriptEngine.eval(LuaScriptEngine.java:95)
	at net.szh.TestLuaj$1.run(TestLuaj.java:27)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
	at java.lang.Thread.run(Thread.java:662)

对照源代码可以看到是因为内部共享了一个LuaFunction数组和数组索引的计数器,导致了此问题。

不过LuaJ已经有3.0版了,不过是beta版的。我第一次看到的时候是3.0-beta1,在3.0的描述中有提到对线程安全做了改进。用 3.0-beta1 跑一下上边的代码可以发现不再有异常抛出。这是一个较为可用的版本。

今年年初的时候,LuaJ发布了 3.0-beta2 版,试用了一下,发现有字符编码问题,可以跑下代码
package net.szh;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class TestLuaj {

    public static void main(String[] args) throws Exception {
        ScriptEngineManager mgr = new ScriptEngineManager();
        ScriptEngine engine = mgr.getEngineByName("luaj");
        engine.eval("--啦啦啦 local i = 0; assert(i)");
    }

}

执行后,会出现如下的异常信息:
Exception in thread "main" javax.script.ScriptException: eval threw javax.script.ScriptException: load script: java.lang.ArrayIndexOutOfBoundsException: 32
	at org.luaj.vm2.script.LuaScriptEngine.compile(LuaScriptEngine.java:94)
	at org.luaj.vm2.script.LuaScriptEngine.eval(LuaScriptEngine.java:112)
	at org.luaj.vm2.script.LuaScriptEngine.eval(LuaScriptEngine.java:106)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247)
	at net.szh.TestLuaj.main(TestLuaj.java:11)

我已经提了bug,并且有人已经找到了问题所在。所以现在还是只有 3.0-beta1 相对可用。

--------------------
2014-10更新
现在已经有了3.0正式版,已经修复了UTF-8编码的bug。
分享到:
评论

相关推荐

    Java调用Lua脚本(LuaJava使用、安装及Linux安装编译)

    一旦LuaJava安装完成,就可以在Java程序中使用它来调用Lua脚本。下面是一个简单的示例: ```java import org.luaj.vm2.*; public class LuaTest { public static void main(String[] args) { // 创建Lua虚拟机 ...

    Jill——Java编写的Lua脚本引擎

    总结来说,Jill为Java开发者提供了在JME环境中无缝集成Lua脚本的能力,大大扩展了Java应用程序的功能性和可定制性。通过学习和熟练掌握Jill,开发者可以利用Lua的简洁性和强大能力,打造更高效、更具有创新性的软件...

    Java下执行Lua脚本工具LuaJava.zip

    LuaJava 是一款专门用于在java下执行lua脚本,该工具的主要目的是允许编写Lua脚本去操作Java组件,不需要任何声明以及任何的预处理。LuaJava 也允许Java去实现一个接口来调用Lua,这样任何的Lua相关接口功能都可以被...

    Java学习资料-Spring Boot - 结合 Redis 使用 Lua脚本

    结合Redis使用Lua脚本可以提升应用的性能和可靠性,特别是在处理高并发、复杂业务逻辑以及事务处理时。以下是对这个主题的详细阐述: 首先,让我们深入了解一下使用Lua脚本在高并发场景中的价值。在并发环境中,...

    SpringBoot+Redis执行lua脚本的方法步骤

    * 在 Java 代码中,使用 `DefaultRedisScript` 执行 Lua 脚本: ```java @Autowired private StringRedisTemplate redisTemplate; @Test public void contextLoads() { String lockKey = "123"; String ...

    java+redis+lua实现重复提交操作拦截.zip

    - 在这个项目中,可能会有一个Lua脚本,用于在Redis中执行锁定和解锁操作,确保整个过程的原子性。例如,脚本可能会检查key是否存在,如果不存在则设置并返回成功,否则失败。 4. **Redis分布式锁**: - 分布式锁...

    luajava-x32-x64.zip

    "说明.txt"文件很可能是对如何集成和使用这些库的详细指南,包括如何加载luajava库,如何在Lua中调用Java类,以及如何在Java中执行Lua脚本等步骤。通常,它会提供示例代码帮助开发者快速上手。 总结来说,luajava-...

    lua脚本解密助手(unluac_2021_12_06.jar)

    适用于lua脚本的解密

    luajava-1.1-x64-lua51

    2. **初始化Lua环境**:在Java代码中创建LuaState对象,这是执行Lua脚本的上下文。 3. **注册Java方法**:使用LuaState的函数将Java方法暴露给Lua,以便在Lua脚本中调用。 4. **执行Lua脚本**:调用LuaState的相应...

    浅析android手游lua脚本的加密与解密(番外篇之反编译的对抗)

    - **背景**:一款使用Lua脚本开发的热门手机游戏,在游戏保护方面采用了多种加密技术。 - **技术细节**:除了基本的字节码加密外,该游戏还使用了自定义虚拟机技术,对Lua字节码的指令序列进行了修改。 - **解题思路...

    LuaJava5.1

    使用LuaJava,开发者无需了解底层的C/C++接口,而是可以直接在Java环境中加载和运行Lua脚本,极大地简化了跨语言交互的过程。 LuaJava的源代码提供给了开发者深入研究和定制的可能性。通过查看和分析源代码,我们...

    luajava实例及jar包,dll动态链接库

    LuaJava是将Lua脚本语言与Java平台紧密结合的一个开源项目,它允许在Java程序中无缝地嵌入和执行Lua代码,从而实现灵活的脚本化功能。这个技术尤其适用于游戏开发、自动化测试、配置管理等领域,因为它提供了快速...

    Lua-1.0.113 luajava

    这对于在Java应用中嵌入Lua脚本或者利用Lua的强大脚本能力处理复杂逻辑非常有用。 LuaJIT的特性包括: 1. 先进的JIT编译器:LuaJIT的动态编译技术能将Lua代码转换成高效的机器码,显著提升运行速度。 2. 兼容性:...

    luajava.zip

    《LuaJava:在Java平台上的Lua脚本引擎详解》 LuaJava是一个强大的工具,它将Lua脚本语言与Java环境紧密地结合起来,使得开发者可以在Java应用程序中无缝地使用Lua脚本进行逻辑处理和扩展功能。在本文中,我们将...

    Lua脚本语言中文教程.pdf

    该语言简单易学,与C、Java等编程语言兼容性好,特别适用于需要脚本编程的场合,比如大型游戏中的剧情控制、手机应用开发等。Lua的执行效率较高,且具备简洁、方便的特点,使得其在IT行业中非常受欢迎。 Lua语言的...

    lua插件包,帮助你搭建lua-java项目

    在Java项目中,你可以通过编写Java代码来创建Lua环境,加载Lua脚本,然后在Java中调用Lua函数,反之亦然。这样可以将复杂逻辑交给Lua处理,而保持Java的稳定性和安全性。 总之,lua插件包提供了一种简单的方法将...

    luajava1.1 64位版本和32位版本

    例如,你可以在Java代码中使用`Luajava.bindClass("java.lang.String")`来绑定Java的String类,然后在Lua脚本中直接创建和操作String对象。同时,luajava还提供了`luajava.newInstance`方法,允许在Lua中实例化Java...

    Javaweb中调用lua的插件

    总结来说,"Javaweb中调用lua的插件"是一个实现Java和Lua互操作的工具,通过luajava库,开发者可以在JavaWeb应用中灵活地使用Lua脚本,同时利用Java的强大功能和稳定性。这对于需要快速迭代和灵活性的项目,尤其是...

Global site tag (gtag.js) - Google Analytics