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

欢迎!请参阅关于页面以获取更多关于如何使用的详情。

0
编译器

在某些我不理解的具体情况下,AOT编译器可能会创建包含对名为thunk0__的字段不一致理解的类文件。

我在https://github.com/ryfow/weird-aot上创建了一个项目,该项目用lein run重现了问题。

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

我怀疑slf4j-timbre被AOT编译,但未被Clojure代码直接加载,这是一个因素。

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

我不明白为什么tools.analyzer和core.async对于展示问题至关重要。

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

`
线程"main"中发生异常 in thread "main" 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抛出异常

线程"main"中发生异常 in thread "main" java.lang.RuntimeException: 方法字节码太大!,编译:(weird_aot/jetty.clj:4:1)

并且无法编译所需的java源代码

编辑它确实编译了java源代码,但没有为Clojure创建或创建默认的编译器输出目录

0

评论由:hiredman

对于从GitHub项目检查的代码使用lein compile没有错误完成编译

0

评论由:hiredman

稍作调整,一些依赖及其临时依赖似乎是采用AOT方式进行编译的,这可能使用了不同版本的Clojure,这并不符合我的预期。使用Clojure版本A编译的aot化代码将无法与使用Clojure版本B编译的代码进行链接

0

评论人:bronsa

我同意Kevin的看法。这个问题高度可能是由于依赖项被分发为AOT引起的,并且存在依赖项冲突。

0

评论由:hiredman

问题在于com.fzakaria/slf4j-timbre "0.2.2"。这个库采用了AOT方式进行编译,递归地对其依赖项进行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编译的,因此引发了一切问题

0

评论人:alexmiller

发布包含AOT依赖项的jar文件肯定是一个问题。我意识到这有一点痛苦,因为CLJ-322(我希望今年能在这方面取得一些进展)。

在这个工单上还有其他需要做的事情吗?

0

评论人:bronsa

我认为我们除⊿了推进CLJ-322和劝导用户不发布AOT编译库外,别无他法

0

评论人:ryfow

对我来说问题在于错误信息。我无法依赖AOT编译的库没有问题,但当我这样做时,错误信息为"java.lang.NoSuchFieldError: thunk0__" 或 "java.lang.RuntimeException: 方法代码过大!"似乎并不好。

0
by

评论人:alexmiller

我明白你的意思。不幸的是,我不确定有没有一种通用的方式来检测这种情况并生成更好的错误。当使用不同版本的库混合时,在Java中也可能发生类似奇怪的问题。

0
by

评论者:aroemers

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

然而,一种解决方法是把{{require}} slf4j-timbre(adapter)命名空间作为编译空间中最先需要的之一。这也与slf4j-timbre库当前的AOT编译版本一起工作。所以,也许解决这个问题的办法与AOT编译库本身无关,而更多与AOT编译期间通过Java类进行命名空间的后续加载有关?

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

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