2024 Clojure状态调查! 中分享您的想法。

欢迎!请参阅关于 页面以了解更多关于其工作方式的信息。

0
编译器

在一些我无法理解的具体情况下,aot编译器可以创建一个名为thickness的类文件,其对我来说是一个不连贯的思想。

我在https://github.com/ryfow/weird-aot 上创建了一个项目,使用 run

重现此问题的成分似乎包括 slf4j-timbre、tools.analyzer 和 core.async。

我怀疑 slf4j-timbre 进行了 aot 编译,但没有被 clojure 代码直接加载,这是一个因素。

注意 weird-aot timbre 版本与 slf4j-timbre 中编译的版本不同。

不清楚为什么 tools.analyzer 和 core.async 是显示此问题的必要条件。

以下是我在 weird-aot 项目上运行 lein run 时得到的堆栈跟踪。

`
在主线程中发生异常 java.lang.NoSuchFieldError: thunk0__,正在编译:(/private/var/folders/2q/tk7cywk93217_d4pxn_5kft40000gn/T/form-init7490372454812250103.clj:1:125)

    at clojure.lang.Compiler.load(Compiler.java:7239)
    at clojure.lang.Compiler.loadFile(Compiler.java:7165)
    at clojure.main$load_script.invoke(main.clj:275)
    at clojure.main$init_opt.invoke(main.clj:280)
    at clojure.main$initialize.invoke(main.clj:308)
    at clojure.main$null_opt.invoke(main.clj:343)
    at clojure.main$main.doInvoke(main.clj:421)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at clojure.lang.Var.invoke(Var.java:383)
    at clojure.lang.AFn.applyToHelper(AFn.java:156)
    at clojure.lang.Var.applyTo(Var.java:700)
    at clojure.main.main(main.java:37)

原因:java.lang.NoSuchFieldError: thunk0__

    at clojure.tools.analyzer.jvm.utils__init.load(Unknown Source)
    at clojure.tools.analyzer.jvm.utils__init.<clinit>(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:340)
    at clojure.lang.RT.classForName(RT.java:2154)
    at clojure.lang.RT.classForName(RT.java:2163)
    at clojure.lang.RT.loadClassForName(RT.java:2182)
    at clojure.lang.RT.load(RT.java:436)
    at clojure.lang.RT.load(RT.java:412)
    at clojure.core$load$fn__5448.invoke(core.clj:5866)
    at clojure.core$load.doInvoke(core.clj:5865)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invoke(core.clj:5671)
    at clojure.core$load_lib$fn__5397.invoke(core.clj:5711)
    at clojure.core$load_lib.doInvoke(core.clj:5710)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invoke(core.clj:632)
    at clojure.core$load_libs.doInvoke(core.clj:5749)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:632)
    at clojure.core$require.doInvoke(core.clj:5832)
    at clojure.lang.RestFn.invoke(RestFn.java:703)
    at clojure.tools.analyzer.jvm$loading__5340__auto____1677.invoke(jvm.clj:9)
    at clojure.tools.analyzer.jvm__init.load(Unknown Source)
    at clojure.tools.analyzer.jvm__init.<clinit>(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:340)
    at clojure.lang.RT.classForName(RT.java:2154)
    at clojure.lang.RT.classForName(RT.java:2163)
    at clojure.lang.RT.loadClassForName(RT.java:2182)
    at clojure.lang.RT.load(RT.java:436)
    at clojure.lang.RT.load(RT.java:412)
    at clojure.core$load$fn__5448.invoke(core.clj:5866)
    at clojure.core$load.doInvoke(core.clj:5865)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invoke(core.clj:5671)
    at clojure.core$load_lib$fn__5397.invoke(core.clj:5711)
    at clojure.core$load_lib.doInvoke(core.clj:5710)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invoke(core.clj:632)
    at clojure.core$load_libs.doInvoke(core.clj:5749)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:632)
    at clojure.core$require.doInvoke(core.clj:5832)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at weird_aot.core$loading__5340__auto____81.invoke(core.clj:1)
    at weird_aot.core__init.load(Unknown Source)
    at weird_aot.core__init.<clinit>(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:340)
    at clojure.lang.RT.classForName(RT.java:2154)
    at clojure.lang.RT.classForName(RT.java:2163)
    at clojure.lang.RT.loadClassForName(RT.java:2182)
    at clojure.lang.RT.load(RT.java:436)
    at clojure.lang.RT.load(RT.java:412)
    at clojure.core$load$fn__5448.invoke(core.clj:5866)
    at clojure.core$load.doInvoke(core.clj:5865)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invoke(core.clj:5671)
    at clojure.core$load_lib$fn__5397.invoke(core.clj:5711)
    at clojure.core$load_lib.doInvoke(core.clj:5710)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invoke(core.clj:632)
    at clojure.core$load_libs.doInvoke(core.clj:5749)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:632)
    at clojure.core$require.doInvoke(core.clj:5832)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at user$eval65$fn__67.invoke(form-init7490372454812250103.clj:1)
    at user$eval65.invoke(form-init7490372454812250103.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:6782)
    at clojure.lang.Compiler.eval(Compiler.java:6772)
    at clojure.lang.Compiler.load(Compiler.java:7227)
    ... 11 more

`

11个答案

0

评论者:hiredman

链接的 GitHub 仓库中的 run.sh 抛出异常

在主线程中发生异常 java.lang.RuntimeException: 方法定义过大!正在编译:(weird_aot/jetty.clj:4:1)

并无法编译所需的 Java 源文件

编辑它确实编译了 Java 源文件,但没有创建 clojure 默认的编译器输出目录

0

评论者:hiredman

对于链接的 GitHub 项目,使用 checkout 运行

0
已回答的

评论者:hiredman

轻微修改了一点点,很多依赖项及其瞬态依赖似乎被AOT编译了,这可能与Clojure的不同版本有关,而这并不是我所预期的。使用Clojure版本A编译的aot代码将无法与新版本的Clojure编译的代码链接。

0
已回答的问题

评论者:bronsa

我同意Kevin的看法。这个问题极可能是由于依赖项以AOT方式分发和依赖项冲突造成的。

0
已回答的问题

评论者:hiredman

com.fzakaria/slf4j-timbre "0.2.2" 是问题所在。这个库被aot编译,并递归地编译其依赖项,这些依赖项是timbre库的老版本,而它们又依赖于旧版本的 tools.reader,因此 com.fzakaria/slf4j-timbre "0.2.2" 的 jar 包包含旧的 tools.reader 编译版本。org.clojure/tools.analyzer.jvm "0.6.9" 使用较新的 tools.reader 版本进行aot编译,所以 everything explodes

0
已回答的问题

评论者:alexmiller

发布包含AOT依赖的jar文件肯定是一个问题。我意识到这个问题因CLJ-322(我希望今年能够真正取得一些进展)而有些痛苦。

这个工单是否还需要做其他什么事?

0
已回答的问题

评论者:bronsa

我认为我们除了推进 CLJ-322 和劝阻用户发布AOT编译的库之外别无选择。

0

评论者:ryfow

对我来说,问题是错误信息。我不依赖AOT编译的库是可以的。但是当我这样做时,错误信息显示为"java.lang.NoSuchFieldError: thunk0__"或"java.lang.RuntimeException: Method code too large!"则似乎有点不合适。

0

评论者:alexmiller

我明白了。不幸的是,我不确定是否有通用方式来检测这种情况,并生成更好的错误信息。在Java中使用不同版本的库时,也可能出现类似的问题。

0

评论者:aroemers

我不确定这个问题只是由于有AOT编译的库。我开始重写slf4j-timbre库的一部分,以消除对AOT的需求(链接:1)。但我在那个版本中发现,当TimbreLoggerAdapter在编译过程中加载slf4j-timbre.adapter命名空间而不是Clojure命名空间时,问题仍然存在。所以每当在编译过程中执行SLF4J日志语句时,运行结果仍然会出现__thunk__问题。

不过一个解决方法是作为第一个AOT编译的命名空间之一,要求提供slf4j-timbre.adapter命名空间。它与slf4j-timbre库的当前AOT编译版本也一起工作。所以可能解决这个问题更多与AOT编译过程中通过Java类进行命名空间间接加载有关,而不仅仅与AOT编译库本身有关?

(链接:1) https://github.com/hellodata-org/slf4j-timbre/blob/f9a2f4469fd92063c261276479593de39fffbee3/src-java/com/github/fzakaria/slf4j/TimbreLoggerAdapter.java

0
参考资料:https://clojure.atlassian.net/browse/CLJ-1886(由ryfow提供报告)
...