欢迎!请参阅 关于 页面以了解如何工作的更多信息。
使用 core/proxy 生成 Java 类的代理会产生在生成的类文件中的不可预测的方法顺序。这对可重复构建(当进行 AOT 时)是一个问题。
具体来说,我在 Docker 中运行 Clojure,并希望我的应用程序镜像层与 Java 开发者生成的(使用 Meta-inf 类路径和 lib 目录)大小一样。无论如何,为了使它正确地工作,以便所有依赖项(包括作为 AOT 编译的一部分)都在单独的一层上,我需要在每次构建时都运行我的应用程序依赖项代理的编译输出相同。这可以减少构建时间、图像推送时间、图像拉取时间和容器调度时间。
表现出问题的示例代码(您需要运行几次以看到问题)。
https://github.com/kipz/predictable-proxies
原因:我已经将其追踪到此处使用了一个未排序的映射
https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_proxy.clj#L186
方法:使用排序的映射,按照键的哈希值排序(键是方法名、参数类型序列和返回类型向量的向量)。
修正:CLJ-1973-v5.patch
审查者:Alex Miller
评论者:kipz
使用 sorted-map 的补丁
由 alexmiller 发布的评论:
我认为您可以参考 https://clojure.org/guides/comparators 中的建议,为这个补丁编写一个更简单的比较器。
按要求,一个非常简单的比较器。
我认为您丢失了排序后的集合。
分支间复制粘贴错误。这次已经测试过。
现在进行了更多一致的 'let' 格式化
虽然这可能没问题,但最好使用Clojure的`hash`函数而不是Java的`hashCode`函数。映射本身基于`hash`进行散列,这似乎更合适。
按照您的要求,使用了Clojure的 'hash' 函数。
谢谢 Alex - 顺便学到了关于布尔比较器的内容!
请注意,这个顺序可能在 Clojure 或 JVM 版本之间发生变化,因为这些版本的哈希没有保证。目前需要进行预筛。