Fork me on GitHub
Christian Johansen08:11:26

clojure.xml/parse gives me reflection warnings on Java 11 - how are people parsing XML in Clojure these days without these warnings? Use Java APIs directly?


could it be "another" kind of reflection warning? i.e. caused by newer JDK intricacies, not by a lack of type hints would help if you post the output here


Prefer instead of clojure.xml

Christian Johansen09:11:40

user=> ( (slurp ( "file.xml")))
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by clojure.lang.InjectedInvoker/0x0000000800232040 (file:/Users/christian/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar) to method
WARNING: Please consider reporting this to the maintainers of clojure.lang.InjectedInvoker/0x0000000800232040
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Execution error (IllegalArgumentException) at (xml.clj:337).
No matching method createXMLStreamReader found taking 1 args for class


yeah, this is more of a JDK issue. I remember this being discussed here like a month ago. Maybe it's archived in Clojurians Zulip?

Ivar Refsdal09:11:02

Running the JVM with --illegal-access=deny will make the warning go away

Ivar Refsdal09:11:25

Though not an optimal solution in my opinion

Ivar Refsdal09:11:01

As of Clojure 1.10, turn off illegal access with --illegal-access=deny. The Java reflection system will then provide the necessary feedback to Clojure to detect that calling through the inaccessible class is not an option. Clojure will find the public invocation path instead and no warning will be issued.

👍 8
Ivar Refsdal11:11:52

No problem. Thanks for a good blog!

Ivar Refsdal12:11:38

Is Clojure class file generation deterministic? I'm getting different .class files on (some) builds. Issue reproduced here:


what does :constructors from gen-class do ?

Edward Hughes14:11:15

I was wondering, what situations would warrant using :require :refer or :refer :all over :require :as ? Aliasing the library in the function name makes the code more legible in terms of knowing where I'm calling things from, which is why I'm sticking with it, but I was curious as to the justifications for the other two syntaxes apart from "code moar faster".


IMHO The only sensible instance of using :refer :all is requiring clojure.test

👍 8

I avoid :refer :all except when pulling in clojure.test

👍 8

@ivar.refsdal no Clojure does not produce deterministic classfiles


what use-case do you have where deterministic classfiles is important?

Ivar Refsdal08:11:38

Classfiles is a part of my container, and I would like my containers to be 100% reproducible, down to the sha256 of the container. A further use-case would be to put library classfiles in a separate layer, and this layer would only change when you change dependencies. The common case for changing only your own source code would likely lead to a tiny layer change at the top. This would reduce disk space usage.

Ivar Refsdal09:11:13

I suppose clojure.lang.RT/id is one cause of the non-determinism. Via Do you know of other causes? And do you think it is reasonable to expect deterministic classfiles?

Ivar Refsdal09:11:44

Not necessarily across Clojure versions, but for the same Clojure version and for the same input.

Ivar Refsdal09:11:42

More specifically my use-case is that I'm putting together use of EwenG/badigeon (Clojure compiler wrapper) and GoogleContainerTools/jib-core But so far I'm not able to reproduce a "complex" container due to the fact that classfiles are changing for the same input.


:require :refer is for symbolic names (like <! , >! in core.async)

Edward Hughes14:11:56

Oh, that makes perfect sense then, thanks.