LuaJ和Android:无法绑定类。

我正在使用LibGDX框架在Java中编写游戏引擎。几个月来,我一直在使用LuaJ 3.0来开发引擎,并且成功地将脚本在Android(在两个设备上测试过)和桌面(在Eclipse中进出)上运行。

然而,今天我尝试部署到Android时,出现了以下错误:

org.luaj.vm2.LuaError: script:2 vm error: java.lang.ClassNotFoundException: com.javamon.console.ScriptPlayerCreate

导致此错误的脚本行是:

Result = luajava.bindClass("com.javamon.console.ScriptPlayerCreate")

这在排版上与Android上所谓“找不到”的类完全相同。

如果我尝试绑定常规Java类(例如java.lang.ClassNotFoundException),我不会收到任何错误。但是,在桌面版本上不会出现此错误,无论是在Eclipse中运行还是通过可运行的* .jar运行。

这是从LogCat检索到的堆栈跟踪:

org.luaj.vm2.LuaError: script:2 vm error: java.lang.ClassNotFoundException: com.javamon.console.ScriptPlayerCreate
  at org.luaj.vm2.lib.jse.LuajavaLib.invoke(Unknown Source)
  at org.luaj.vm2.lib.VarArgFunction.call(Unknown Source)
  at org.luaj.vm2.LuaClosure.execute(Unknown Source)
  at org.luaj.vm2.LuaClosure.call(Unknown Source)
  at com.javamon.console.Script.runFunction(Script.java:91)
  at com.javamon.console.Script.runFunction(Script.java:96)
  at com.javamon.console.ScriptPlayerCreate.run(ScriptPlayerCreate.java:39)

令我困扰的是最后一行。ScriptPlayerCreate肯定存在-_它正在运行产生错误的脚本!

我尝试过的事情:

  • 尝试不同版本的LuaJ
  • com.javamon包内绑定不同的类(同样的问题)
  • 更新我的ADT/SDK插件
  • 在Eclipse中清理/重建项目
  • “重新开始”(使用GUI工具创建新的LibGDX项目,并手动导入我的源文件)
  • 检查classes.dex-_ScriptPlayerCreate肯定在那里
  • 在单独的Android设备上进行测试(Moto X和Incredible 2)

我想重申,我已经成功使用LuaJ和Android进行开发_几个月_而没有事故。此外,自我上一次(成功)Android部署以来,我没有更改我的脚本引擎。

更新

尝试回到我的应用和Eclipse的备份版本后,问题仍然存在-_甚至在另一台计算机上也是如此。我开始怀疑luajava.bindClass()不知道如何解释classes.dex的内容,而是在搜索实际的类文件。

当我试图重新编译一些备份版本时,我注意到重新编译的版本几乎总是具有比备份更小的classes.dex文件。也许Eclipse/Android的编译器出了问题或发生了变化?

我尝试手动将类文件插入APK内的com/javamon/console/文件夹中,但当然会破坏文件完整性,并且即使重新签名应用程序也无法加载。有什么想法?

点赞
用户3525774
用户3525774

将下面翻译成中文并且保留原本的 markdown 格式:

回退到LuaJ 2.0.1解决了这个问题。

似乎所有2.0.1以上版本的LuaJ都对LuajavaLib.class有不同的实现。在新的实现中,只有Java系统库可以通过luajava.bindClass()进行访问,而在旧版本中,bindClass()允许访问本地应用程序类。所有其他脚本函数的行为都正常;只有luajava.bindClass()受到影响。

在更新的版本中,如果Java系统库中找不到类,LuaJ似乎会检查本地应用程序目录。由于Desktop项目是一个可运行的* .jar文件,并包含实际的“class”文件,因此桌面版本的游戏在任何版本的LuaJ中都会正常工作。相反,Android将所有文件打包在一个classes.dex文件中,该文件在文件路径上不可“搜索”。因此出现了“ClassNotFoundException”。

最后:我已经成功使用LuaJ几个月了,发生了什么变化?几个月前升级到3.0时,Eclipse实际上从未识别文件更改。只有当我刷新并清理项目时,Eclipse才意识到新版本的LuaJ存在。因为LibGDX中的主要项目仅为源文件(资源位于“-android”中),您几乎永远不会点击“刷新”。因此,LuaJ问题就像是一个定时炸弹。

我计划向作者提交支持票,以便他可以解决这个问题。在他这样做之前,我建议Android开发人员继续使用LuaJ 2.0.1!

2014-04-14 01:23:12
用户4136998
用户4136998

我遇到了类似的问题,我处理了它:

LuaJavaLib.java 的第 202 行:

原始代码:

return Class.forName(name, true, **ClassLoader.getSystemClassLoader**());

修改后代码:

return Class.forName(name, true, **Thread.currentThread().getContextClassLoader**());
2014-10-13 10:15:31
用户1052261
用户1052261

你可以使用自己的 Helper 类来修复它。

创建包:org.luaj.vm2.lib.jse 在该包中创建以下类:

package org.luaj.vm2.lib.jse;

public class Helper {
    public static JavaClass forClass(Class c) {
        return JavaClass.forClass(c);
    }

    public Class<JavaClass> huskClass() {
        return JavaClass.class;
    }
}

然后创建类似桥接的类:

public class LuaBridge {
        public Varargs getClass(String clazzName) {
        try {
            Class clazz = Class.forName(clazzName);
            return Helper.forClass(clazz);
        } catch (Exception e) {
            e.printStackTrace();
            Crashlytics.logException(e);
        }
        return null;
    }
}

现在当你运行你的脚本时,你可以把实例传给你的 Lua 脚本:

_globals = JsePlatform.standardGlobals();
_bridge = new LuaBridge();
//...
    _globals.loadfile(scriptName)
            .call(CoerceJavaToLua.coerce(_bridge));

在你的 LUA 脚本中:

第一行:

local luaBridge = ...
-- some code here...
UserManager = luaBridge:getClass("com.dexode.cree.ScriptPlayerCreate")
-- used like luajava.bindClass("com.dexode.cree.ScriptPlayerCreate")
2015-04-15 10:35:49