以 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)。