首页 > 解决方案 > 在 Android 上运行 Clojure:“无法加载这种类型的类文件”

问题描述

我正在尝试让 Clojure 和 JavaFXPorts 在 Android 上运行。但它在启动时崩溃,并带有以下堆栈跟踪。我对 JVM 内部的了解太少,所以我不知道为什么会发生这种特殊的 UnsupportedOperationException。我的假设是 Clojure 使用其编译器注册了一个新的类文件类型,由于某种原因,这在 Android 上失败了——至少与 JavaFXPorts 结合使用(我没有尝试在没有 JavaFXPorts 的情况下创建 Android 应用程序;我将需要它反正)。

10-30 19:00:24.450 11088 11130 W System.err: java.lang.reflect.InvocationTargetException
10-30 19:00:24.450 11088 11130 W System.err:    at java.lang.reflect.Method.invoke(Native Method)
10-30 19:00:24.450 11088 11130 W System.err:    at javafxports.android.DalvikLauncher$1.run(DalvikLauncher.java:188)
10-30 19:00:24.451 11088 11130 W System.err:    at java.lang.Thread.run(Thread.java:761)
10-30 19:00:24.452 11088 11130 W System.err: Caused by: java.lang.RuntimeException: Unable to construct Application instance: class lyrion.cec.core
10-30 19:00:24.452 11088 11130 W System.err:    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:907)
10-30 19:00:24.452 11088 11130 W System.err:    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$138(LauncherImpl.java:182)
10-30 19:00:24.453 11088 11130 W System.err:    at com.sun.javafx.application.LauncherImpl.access$lambda$1(LauncherImpl.java)
10-30 19:00:24.453 11088 11130 W System.err:    at com.sun.javafx.application.LauncherImpl$$Lambda$2.run(Unknown Source)
10-30 19:00:24.453 11088 11130 W System.err:    ... 1 more
10-30 19:00:24.454 11088 11130 W System.err: Caused by: java.lang.ExceptionInInitializerError
10-30 19:00:24.454 11088 11130 W System.err:    at java.lang.Class.classForName(Native Method)
10-30 19:00:24.454 11088 11130 W System.err:    at java.lang.Class.forName(Class.java:400)
10-30 19:00:24.454 11088 11130 W System.err:    at clojure.lang.RT.classForName(RT.java:2204)
10-30 19:00:24.454 11088 11130 W System.err:    at clojure.lang.RT.classForName(RT.java:2213)
10-30 19:00:24.455 11088 11130 W System.err:    at clojure.lang.RT.loadClassForName(RT.java:2232)
10-30 19:00:24.455 11088 11130 W System.err:    at clojure.lang.RT.load(RT.java:450)
10-30 19:00:24.455 11088 11130 W System.err:    at clojure.lang.RT.load(RT.java:426)
10-30 19:00:24.455 11088 11130 W System.err:    at clojure.lang.RT.doInit(RT.java:468)
10-30 19:00:24.455 11088 11130 W System.err:    at clojure.lang.RT.<clinit>(RT.java:336)
10-30 19:00:24.455 11088 11130 W System.err:    at clojure.lang.Namespace.<init>(Namespace.java:34)
10-30 19:00:24.456 11088 11130 W System.err:    at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
10-30 19:00:24.456 11088 11130 W System.err:    at clojure.lang.Var.internPrivate(Var.java:153)
10-30 19:00:24.456 11088 11130 W System.err:    at lyrion.cec.core.<clinit>(Unknown Source)
10-30 19:00:24.456 11088 11130 W System.err:    at java.lang.reflect.Constructor.newInstance0(Native Method)
10-30 19:00:24.456 11088 11130 W System.err:    at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
10-30 19:00:24.456 11088 11130 W System.err:    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$144(LauncherImpl.java:819)
10-30 19:00:24.457 11088 11130 W System.err:    at com.sun.javafx.application.LauncherImpl.access$lambda$7(LauncherImpl.java)
10-30 19:00:24.457 11088 11130 W System.err:    at com.sun.javafx.application.LauncherImpl$$Lambda$8.run(Unknown Source)
10-30 19:00:24.457 11088 11130 W System.err:    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$158(PlatformImpl.java:326)
10-30 19:00:24.457 11088 11130 W System.err:    at com.sun.javafx.application.PlatformImpl.access$lambda$6(PlatformImpl.java)
10-30 19:00:24.457 11088 11130 W System.err:    at com.sun.javafx.application.PlatformImpl$$Lambda$7.run(Unknown Source)
10-30 19:00:24.457 11088 11130 W System.err:    at com.sun.javafx.application.PlatformImpl.lambda$null$156(PlatformImpl.java:295)
10-30 19:00:24.458 11088 11130 W System.err:    at com.sun.javafx.application.PlatformImpl.access$lambda$18(PlatformImpl.java)
10-30 19:00:24.458 11088 11130 W System.err:    at com.sun.javafx.application.PlatformImpl$$Lambda$19.run(Unknown Source)
10-30 19:00:24.458 11088 11130 W System.err:    at java.security.AccessController.doPrivileged(AccessController.java:57)
10-30 19:00:24.458 11088 11130 W System.err:    at com.sun.javafx.application.PlatformImpl.lambda$runLater$157(PlatformImpl.java:294)
10-30 19:00:24.458 11088 11130 W System.err:    at com.sun.javafx.application.PlatformImpl.access$lambda$5(PlatformImpl.java)
10-30 19:00:24.458 11088 11130 W System.err:    at com.sun.javafx.application.PlatformImpl$$Lambda$6.run(Unknown Source)
10-30 19:00:24.459 11088 11130 W System.err:    at com.sun.glass.ui.monocle.RunnableProcessor.runLoop(RunnableProcessor.java:93)
10-30 19:00:24.459 11088 11130 W System.err:    at com.sun.glass.ui.monocle.RunnableProcessor.run(RunnableProcessor.java:52)
10-30 19:00:24.459 11088 11130 W System.err:    ... 1 more
10-30 19:00:24.460 11088 11130 W System.err: Caused by: java.lang.UnsupportedOperationException: can't load this type of class file, compiling:(clojure/core_instant18.clj:9:1)
10-30 19:00:24.460 11088 11130 W System.err:    at clojure.lang.Compiler.analyzeSeq(Compiler.java:7010)
10-30 19:00:24.461 11088 11130 W System.err:    at clojure.lang.Compiler.analyze(Compiler.java:6773)
10-30 19:00:24.461 11088 11130 W System.err:    at clojure.lang.Compiler.eval(Compiler.java:7059)
10-30 19:00:24.461 11088 11130 W System.err:    at clojure.lang.Compiler.load(Compiler.java:7514)
10-30 19:00:24.493 11088 11130 W System.err:    at clojure.lang.RT.loadResourceScript(RT.java:379)
10-30 19:00:24.494 11088 11130 W System.err:    at clojure.lang.RT.loadResourceScript(RT.java:370)
10-30 19:00:24.494 11088 11130 W System.err:    at clojure.lang.RT.load(RT.java:460)
10-30 19:00:24.494 11088 11130 W System.err:    at clojure.lang.RT.load(RT.java:426)
10-30 19:00:24.494 11088 11130 W System.err:    at clojure.core$load$fn__6548.invoke(core.clj:6046)
10-30 19:00:24.494 11088 11130 W System.err:    at clojure.core$load.invokeStatic(core.clj:6045)
10-30 19:00:24.495 11088 11130 W System.err:    at clojure.core$load.doInvoke(core.clj:6029)
10-30 19:00:24.495 11088 11130 W System.err:    at clojure.lang.RestFn.invoke(RestFn.java:408)
10-30 19:00:24.495 11088 11130 W System.err:    at clojure.core$fn__8055.invokeStatic(core.clj:6709)
10-30 19:00:24.495 11088 11130 W System.err:    at clojure.core$fn__8055.invoke(core.clj:6708)
10-30 19:00:24.495 11088 11130 W System.err:    at clojure.core__init.load(Unknown Source)
10-30 19:00:24.495 11088 11130 W System.err:    at clojure.core__init.<clinit>(Unknown Source)
10-30 19:00:24.496 11088 11130 W System.err:    ... 31 more
10-30 19:00:24.497 11088 11130 W System.err: Caused by: java.lang.UnsupportedOperationException: can't load this type of class file
10-30 19:00:24.497 11088 11130 W System.err:    at java.lang.ClassLoader.defineClass(ClassLoader.java:520)
10-30 19:00:24.497 11088 11130 W System.err:    at clojure.lang.DynamicClassLoader.defineClass(DynamicClassLoader.java:46)
10-30 19:00:24.497 11088 11130 W System.err:    at clojure.lang.Compiler$ObjExpr.getCompiledClass(Compiler.java:4979)
10-30 19:00:24.498 11088 11130 W System.err:    at clojure.lang.Compiler$FnExpr.parse(Compiler.java:4109)
10-30 19:00:24.498 11088 11130 W System.err:    at clojure.lang.Compiler.analyzeSeq(Compiler.java:7001)
10-30 19:00:24.498 11088 11130 W System.err:    ... 46 more

标签: androidgradleclojurejvmjavafxports

解决方案


首先是剧透:对于 Clojure,它已经完成了。

问题是 Clojure 有一个DynamicClassLoader你可能猜到的,它加载在运行时组成的类,而 Android 不支持它。实际上,您可以通过 JVM 在 JVM 上ClassLoader.defineClass()执行此操作,但该方法在 Android 上的实现只会抛出您看到的异常,这意味着 Clojure 甚至无法在 Android 上初始化。

另一个问题是,即使该方法可用,Android 也无法运行 Clojure 生成的 JVM 字节码,正是因为它是 JVM 字节码。

幸运的是,这位英雄通过添加另一个动态解决了这个问题,ClassLoader它将动态类的字节转换为 DEX 文件,然后到 ODEX 以供 Android 运行时接受它(如果与 Android Studio 上的 Instant Run 不一样的话,非常相似)。

不幸的是,那是在 2011 年,他的Clojure 分叉已经四年没有维护了。

您可以看到 Clojure 的 Android fork 的作者在 ClojureConj 2011 的精彩演讲中对此进行了解释。


推荐阅读