欢迎!请访问关于页面以了解更多此网站的工作方式。
使用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 版本的不同而发生变化,因为这些版本之间没有哈希保证。目前进行预筛选。