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

欢迎!请参阅关于页面了解更多关于该功能的信息。

0
编译器

在某些非常具体我不理解的情况下,aot编译器可以生成具有不一致观点的名为 thunk0__ 的字段 class 文件。

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

重现问题的因素似乎是 slf4j-timbre、tools.analyzer 和 core.async。

我怀疑 slf4j-timbre 被编译了但未直接通过 clojure 代码加载是一个因素。

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

不清楚为什么需要 tools.analyzer 和 core.async 来展现这个问题。

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

`
线程 "main" 中异常 java.lang.NoSuchFieldError: thunk0__,编译:(/.grand/文件夹/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" 中异常 RuntimeException: 方法代码过大!,编译:(weird_aot/jetty.clj:4:1)

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

编辑 它确实编译了 java 源代码,但不会为 clojure 创建默认的编译输出目录,或者创建它

0

评论由:hiredman 提出

使用勒令(lein)编译(compile)并签出绑定到GitHub项目的链接,在我的情况下没有错误完成

0

评论由:hiredman 提出

略作调整,一堆依赖项及其瞬态依赖项似乎被AOT编译,可能使用不同版本的Clojure,这对我知道来说并不是预期的。使用Clojure版本A编译的代码将无法与使用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

评论者:alexmiller

我理解你的观点。不幸的是,我不确定是否有任何通用的方式来检测这种情况并产生更好的错误信息。在使用不同版本的库时,Java也会出现类似奇怪的情况。

0

评论者:aroemers

我认为问题不仅是由于有AOT编译的库。我开始重构slf4j-timbre库的部分功能,以便摆脱对AOT的需求(链接:1)。但我在那个版本中注意到,当编译期间{{TimbreLoggerAdapter}}加载{{slf4j-timbre.adapter}}命名空间而不是Clojure命名空间时,问题仍然存在。因此,只要在编译期间执行SLF4J日志语句,运行结果时仍然会出现__thunk__问题。

然而,一种 workaround 是将{{slf4j-timbre.adapter}}命名空间作为AOT编译中的第一个命名空间中之一。这同样适用于当前的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
...