Reputation: 1603
Although I believe I have a solid beginner's understanding of Clojure, I am fairly at sea when interoperating with Java.
Thus I am struggling to fix some (unavoidable) interop code that generates JVM warnings. This is the code, it takes a W3C dom node and creates an LS serializer from it so I can spit out the corresponding XML string:
(defn serializer
[node]
(let [serializer (-> node
.getOwnerDocument
.getImplementation
.createLSSerializer)]
(.setParameter (.getDomConfig serializer) "xml-declaration" false)
serializer))
The code works fine and did not result in warnings until a recent system update.
But JVM (for openjdk 11.0.10) does not seem to like the call to .getOwnerDocument
and it also does not like the call to .getImplementation
as I discovered when I rewrote to avoid the call to .getOwnerDocument
. The exact warning (arrows/linebreaks added):
WARNING: Illegal reflective access by clojure.lang.InjectedInvoker/0x00000008401e8040
(file:/home/user/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar)
-->to method com.sun.org.apache.xerces.internal.dom.NodeImpl.getOwnerDocument()<--
WARNING: Please consider reporting this to the maintainers of clojure.lang.InjectedInvoker/0x00000008401e8040
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
From this StackOverflow discussion it appears casting should be involved in the call to .getImplementation
, like so:
DOMImplementationLS domImplementation = (DOMImplementationLS) doc.getImplementation();
LSSerializer lsSerializer = domImplementation.createLSSerializer();
This discussion seems to indicate that casting is not needed in Clojure and you can avoid reflection by type hinting:
(defn bar [^String x]
(.toCharArray x))
So I rewrote my function to use type hinting:
(defn serializer
[^com.sun.org.apache.xerces.internal.dom.NodeImpl node]
(let [serializer (-> node
.getOwnerDocument
.getImplementation
.createLSSerializer)]
(.setParameter (.getDomConfig serializer) "xml-declaration" false)
serializer))
This seems to get me past warnings on .getOwnerDocument
and .getImplementation
. But now it's warning me about the call to .createLSSerializer
, which is a bit frustrating as I seem to be calling this last method exactly and on the same type of object as the well upvoted answer I quoted from this discussion above. This is the error I get with the type hinting (arrows/linebreaks added):
WARNING: Illegal reflective access by clojure.lang.InjectedInvoker/0x00000008401e8040
(file:/home/user/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar)
-->to method com.sun.org.apache.xerces.internal.dom.CoreDOMImplementationImpl.createLSSerializer()<--
WARNING: Please consider reporting this to the maintainers of clojure.lang.InjectedInvoker/0x00000008401e8040
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
If anyone has ideas on how to resolve this, or suggested areas for me to read up on in Java, I'd be very grateful. Thanks for any help.
Upvotes: 3
Views: 595
Reputation: 1603
Apparently, the answer was to provide an additional type hint, like so:
(defn serializer
[^com.sun.org.apache.xerces.internal.dom.NodeImpl node]
(let [serializer (-> node
.getOwnerDocument
^com.sun.org.apache.xerces.internal.dom.CoreDOMImplementationImpl
(.getImplementation)
.createLSSerializer)]
(.setParameter (.getDomConfig serializer) "xml-declaration" false)
serializer))
I discovered this thanks to a "related" question/answer Stackoverflow found and placed next to my question, specifically these. Apologies for not finding it earlier, perhaps this thread will provide some help if someone hits the same issue.
Upvotes: 4