This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-05-17
Channels
- # aws (3)
- # beginners (104)
- # boot (11)
- # calva (3)
- # clj-kondo (1)
- # cljdoc (6)
- # cljs-dev (23)
- # cljsrn (1)
- # clojure (144)
- # clojure-dev (54)
- # clojure-europe (6)
- # clojure-italy (2)
- # clojure-nl (26)
- # clojure-spec (6)
- # clojure-sweden (1)
- # clojure-uk (13)
- # clojurescript (38)
- # core-async (9)
- # cursive (14)
- # data-science (3)
- # datascript (22)
- # datomic (17)
- # figwheel (1)
- # fulcro (4)
- # graphql (6)
- # hoplon (59)
- # jackdaw (2)
- # jobs (6)
- # jobs-discuss (44)
- # juxt (14)
- # leiningen (1)
- # luminus (3)
- # nrepl (3)
- # off-topic (12)
- # re-frame (24)
- # reagent (7)
- # reitit (7)
- # rewrite-clj (1)
- # schema (1)
- # shadow-cljs (37)
- # spacemacs (4)
- # sql (25)
- # testing (12)
- # tools-deps (11)
- # utah-clojurians (1)
I’ve just seen this WARNING on clojure 1.10.0 on jdk 12: > WARNING: An illegal reflective access operation has occurred >WARNING: Illegal reflective access by clojure.lang.InjectedInvoker/0x0000000801182440 (file:/Users/rick/.m2/repository/org/clojure/clojure/1.10.0/clojure-1.10.0.jar) to method com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl.getYear() > WARNING: Please consider reporting this to the maintainers of clojure.lang.InjectedInvoker/0x0000000801182440 > 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 I suspect it’s a known issue
I see that all the time, and also suspect it's a known issue 🙂
I'd suspect that this isn't actually an issue in Clojure but rather some library relying on reflection and the JDK blaming the wrong thing for it
the reflection happens in Clojure (at the behest of code doing reflection)
InjectedInvoker
doesn't appear in the clojure source at all, curiously
the question is - who is calling getYear on a calendar impl?
what's the policy change here anyhow? what kind of reflection is no longer allowed?
@rickmoynihan use --illegal-access=debug
and it will tell you where it's happening
thanks alex & ghadi
well the stack trace may just be the clojure compiler, which would not tell you
depends whether it's compile-time or run-time reflective determination being made
is that just the distinction between (def foobar (.getYear coolCalendar))
and (defn jhomason [] (.getYear coolCalendar))
, or something more subtle?
yes, that, I believe
coolthx
ok thanks that gives me a decent stacktrace… thankfully it also looks like it’s in one of my libraries, so I can take a look at it
@rickmoynihan public library?
@alexmiller the compiler should be free to reflect without warning, no? it's only usage/invocation that incurs the illegal access warning
iirc it uses the javax xml calendar for some type coercions — so I guess this is unsurprising
it has to read xsd datatypes so it needs to do something like that
we coerce them to java.time; but have to read XSD representations off the wire so to speak
will shave this yak another day
yeah it’s a really gross API… but RDF borrows its data types from xsd - so needs must.
the main job grafter does is coerce that gunk into proper values
@ghadi when you say the compiler should be free to reflect, do you mean the compiler should be free to generate reflection code?
I mean the compiler should be free to enumerate a class's methods, even inaccessible ones. If it generates bytecode that refers to an inaccessible method, that's where the warning will happen -- in runtime, not in the compiler
yeah, right
so (def foo-bar (.getYear coolCalendar))
might warn/throw, but the stack would at least point to the line in question despite having lots of compiler frames in it, I think
so I'm not sure what Mister Miller was worried about
so that example is interesting because it's runtime reflective - as you say it will have extra frames in it -- but I don't think there will be any compiler frames
but the code runs at compile-time
I retract my worry
I'm running a nested java.jdbc query, trying to process both result sets lazily in parallel, and am not getting the head-holding-OOM I expected, and I'm curious to understand why the simplest version of the structure is:
(jdbc/query ...
{:result-set-fn
(fn [xs]
(jdbc/query ...
{:result-set-fn
(fn [ys] (reduce ... (map vector xs ys)))}))})
I would have expected that I need to use ^:once fn*
on the inner function so that the closure-reference to xs
gets released early and there's no head-holdingthe only way I can imagine this is working anyhow is if we have this sequence of events
1. .invoke
called on the inner function
2. inner function essentially passes xs
to reduce
3. jvm notices that the instance variable xs
won't be used again in the invoke
method
4. AND the jvm notices that the instance of the inner function isn't going to be used again either
5. and so concludes that the head of xs
is unreachable
is this really happening because it sounds too fancy to be true
I dunno maybe it isn't
I guess it just never occurred to me that the jvm could tell a function was being called for the last time
Your description above sounds like what I understand escape analysis to be. I’ve no idea if it’s happening; but escape analysis is something the JVM does; and it is something it’s getting better at. So what you say sounds plausible to me.
I think it is entirely possible it is just locals clearing, but you would want to look at the bytecode to be sure
the clojure compiler can't know the function is only going to be called once
if it might be called again, you have to hold onto the head, just in case