欢迎!请参阅关于页面以获取有关该页面如何工作的更多信息。
使用 core/proxy 为 Java 类生成代理在生成的类文件中产生不可预测的方法顺序。这对可重复构建(进行 AOT 时)来说是一个问题。
具体来说,我正在 Docker 内运行 Clojure,并希望我的应用程序镜像层尽可能小,与应用程序开发者生成的镜像层大小相当(使用 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'
虽然这可能没问题,但是最好使用{{hash}}(Clojure)函数而不是{{.hashCode}}(Java)函数。映射本身是根据{{hash}}来计算哈希值的,因此这似乎更合适。
如请求,改用Clojure 'hash'函数。
感谢Alex - 还学习了布尔比较器!
请注意,由于这些版本之间没有哈希的保证,此排序可能会在不同版本的Clojure或JVM之间发生变化。目前先进行预筛选。