Welcome! Please see the About page for a little more info on how this works.

0 votes
in Compiler by

Using core/proxy to generate proxies for Java classes produces unpredictable method ordering in the generated class files.
This is a problem for repeatable builds (when doing AOT).

Specifically, I'm running Clojure inside Docker, and I'd like my application image layer to be as small as those produced by Java developers (using Meta-inf classpaths and a lib directory). Anyway, to get this working properly so that all dependencies (including those compiled as part of AOT) are on a separate layer, I need the output of compiling my applications' dependencies' proxies to be the same each time I run the build. This reduces build time, image push time, image pull time and container scheduling time.

Example code that exhibits the problem (you'll need to run it a few times to see the issue).

https://github.com/kipz/predictable-proxies

Cause: I've tracked it down to the use of an unsorted map here:

https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_proxy.clj#L186

Approach: Use a sorted map, sorted by hash of the key (which is a vector of method name, seq of param types, and return type).

Patch: CLJ-1973-v5.patch

Screened by: Alex Miller

10 Answers

0 votes
by

Comment made by: kipz

Patch that uses a sorted-map

0 votes
by

Comment made by: alexmiller

I think you can follow the advice at http://clojure.org/guides/comparators to write a simpler comparator for this patch.

0 votes
by

Comment made by: kipz

Simpler comparator as requested.

0 votes
by

Comment made by: alexmiller

I think you lost the sorted set.

0 votes
by

Comment made by: kipz

Copy paste between branches error. Tested this time.

0 votes
by

Comment made by: kipz

Now with more consistent formatting of 'let'

0 votes
by

Comment made by: alexmiller

While this is probably fine, it might be better to use the {{hash}} (Clojure) function rather than {{.hashCode}} (Java) function. The map itself is hashed based on the {{hash}} so that seems more appropriate.

0 votes
by

Comment made by: kipz

As requested, using Clojure 'hash' instead.

Thanks Alex - learned about boolean comparators too!

0 votes
by

Comment made by: alexmiller

Note that this ordering may still change across Clojure or JVM versions as there is no guarantee of hashing across those. Pre-screening for now.

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-1973 (reported by kipz)
...