【问题标题】:LuaJ and Android: cannot bind classLuaJ 和 Android:无法绑定类
【发布时间】:2014-05-26 09:22:46
【问题描述】:

我目前正在使用 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/ 文件夹,但这当然会破坏文件完整性,即使重新签名后应用程序也不会加载。有什么想法吗?

【问题讨论】:

    标签: java android eclipse lua libgdx


    【解决方案1】:

    我遇到了类似的问题,我会解决的

    LuaJavaLib.java:202

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

    更改为 return Class.forName(name, true, Thread.currentThread().getContextClassLoader());

    【讨论】:

      【解决方案2】:

      恢复到 LuaJ 2.0.1 解决了这个问题。

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

      在较新的版本中,如果在 Java 系统库中找不到某个类,LuaJ 显然会检查本地应用程序目录。因为桌面项目是一个可运行的 *.jar 并且包含实际的class 文件,所以桌面版本的游戏可以在任何版本的 LuaJ 中正常工作。相比之下,Android 将所有内容捆绑在一个 classes.dex 文件中,这在文件路径意义上不是“可搜索的”。因此ClassNotFoundException

      最后:我已经成功使用 LuaJ 几个月了,有什么变化吗?显然,当我几个月前升级到 3.0 时,Eclipse 从未真正识别出文件更改。只有当我刷新和清理项目时,Eclipse 才意识到出现了新版本的 LuaJ。因为 LibGDX 中的主要项目只是源文件(资产在-android),你几乎从不点击“刷新”。因此,LuaJ 问题就像一颗定时炸弹。

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

      【讨论】:

        【解决方案3】:

        你也可以用你的类助手修复它。

        创建包: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")
        

        【讨论】:

          猜你喜欢
          • 2016-06-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-23
          • 1970-01-01
          • 2018-10-16
          • 1970-01-01
          • 2014-12-21
          相关资源
          最近更新 更多