请在 2024 年 Clojure 状态调查中分享您的想法!

欢迎!请参阅 关于页面 了解更多有关此如何工作的信息。

0
编译器

以 clojure/tools.logging 为例。

重现
- 对 clojure/tools.logging 中的所有命名空间进行 AOT 编译(clojure.tools.logging 和 clojure.tools.logging.impl)
- 将结果放在类路径上,使用 AOT 编译 clojure/java.data(clojure.java.data)
- 观察第二次编译的输出中的 clojure/tools/logging$eval32$fn__33.class(确保为这两个编译使用不同的输出目录)。

这通常无害,但如果尝试缓存 AOT 编译输出,则可能会引起问题。当以这种方式尝试缓存以前的 AOT 运行时,有时会得到两个本来无关的命名空间生成相同的文件名。如果它们的内容相同,那就没问题,但是没有保证它们的内容相同(因为 32 和 33 只是 gensym)。根据类路径上哪一个“获胜”,可能会导致严重后果。

我不是这方面的专家,但最好是将这些“额外”类的生成作为 tools.logging 的一部分,或者以某种方式别名到编译其的命名空间中(例如,clojure/java/data/$clojure$tools$logging$eval32$fn__33.class 或 clojure/tools/logging/$clojure$java$data$eval32$fn_33.class)。

2 个答案

0

评论由:hiredman 提出

tools.logging 使用 eval 在类路径上存在某些类时生成一些代码,eval 生成类文件,当开启 AOT 编译时,这些类文件将输出到文件系统。

名称之所以如此,是因为在 tools.logging 命名空间加载时执行 eval,所以 ns 变量的值是 tools.logging 命名空间,这是编译器根据其生成名称的。

0
参考: https://clojure.atlassian.net/browse/CLJ-1916(由 alex+import 报告)
...