欢迎!请查看关于页面以了解有关此工作的一些更多信息。
使用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之间发生变化,因为无法保证这些版本的哈希值。目前请在预审阶段进行。