clojure-dev

Issues: https://clojure.atlassian.net/browse/CLJ | Guide: https://insideclojure.org/2015/05/01/contributing-clojure/
2019-05-17T14:22:57.169200Z

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

2019-05-17T14:23:44.169500Z

I see that all the time, and also suspect it's a known issue 🙂

thheller 2019-05-17T15:08:37.170200Z

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

alexmiller 2019-05-17T15:11:38.170500Z

yes

alexmiller 2019-05-17T15:11:56.171100Z

the reflection happens in Clojure (at the behest of code doing reflection)

2019-05-17T15:12:06.171300Z

InjectedInvoker doesn't appear in the clojure source at all, curiously

alexmiller 2019-05-17T15:12:44.171600Z

the question is - who is calling getYear on a calendar impl?

2019-05-17T15:13:52.172100Z

what's the policy change here anyhow? what kind of reflection is no longer allowed?

alexmiller 2019-05-17T15:14:35.172300Z

https://clojure.org/guides/faq#illegal_access

ghadi 2019-05-17T15:14:58.172700Z

@rickmoynihan use --illegal-access=debug and it will tell you where it's happening

ghadi 2019-05-17T15:15:06.172900Z

it will dump a stacktrace

2019-05-17T15:15:18.173300Z

thanks alex & ghadi

alexmiller 2019-05-17T15:15:21.173500Z

well the stack trace may just be the clojure compiler, which would not tell you

alexmiller 2019-05-17T15:15:44.173900Z

depends whether it's compile-time or run-time reflective determination being made

2019-05-17T15:17:28.174700Z

is that just the distinction between (def foobar (.getYear coolCalendar)) and (defn jhomason [] (.getYear coolCalendar)), or something more subtle?

2019-05-17T15:19:25.175500Z

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

alexmiller 2019-05-17T15:22:37.175600Z

yes, that, I believe

2019-05-17T15:24:06.175800Z

coolthx

ghadi 2019-05-17T15:24:14.176100Z

@rickmoynihan public library?

2019-05-17T15:24:27.176300Z

yeah

2019-05-17T15:24:41.176700Z

https://github.com/Swirrl/grafter

ghadi 2019-05-17T15:25:18.177800Z

@alexmiller the compiler should be free to reflect without warning, no? it's only usage/invocation that incurs the illegal access warning

2019-05-17T15:25:21.178Z

iirc it uses the javax xml calendar for some type coercions — so I guess this is unsurprising

ghadi 2019-05-17T15:25:44.178400Z

boooooooo

2019-05-17T15:27:43.179500Z

it has to read xsd datatypes so it needs to do something like that

ghadi 2019-05-17T15:27:55.179800Z

ah

2019-05-17T15:28:18.180200Z

we coerce them to java.time; but have to read XSD representations off the wire so to speak

2019-05-17T15:29:07.180500Z

will shave this yak another day

ghadi 2019-05-17T15:29:57.181200Z

sounds like you have an actually legit usage of javax.xml for date formatting

ghadi 2019-05-17T15:30:02.181400Z

perhaps the world's first 😂

2019-05-17T15:30:20.181800Z

@ghadi when you say the compiler should be free to reflect, do you mean the compiler should be free to generate reflection code?

ghadi 2019-05-17T15:31:54.183600Z

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

alexmiller 2019-05-17T15:32:08.183900Z

yeah, right

ghadi 2019-05-17T15:32:16.184200Z

enumeration doesn't ever warn

2019-05-17T15:32:51.185100Z

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

ghadi 2019-05-17T15:32:54.185400Z

meaning --illegal-access=debug is a reliable method to get accurate traces

2019-05-17T15:33:00.185600Z

so I'm not sure what Mister Miller was worried about

2019-05-17T15:33:30.186100Z

yeah it’s a really gross API… but RDF borrows its data types from xsd - so needs must.

ghadi 2019-05-17T15:34:04.186800Z

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

2019-05-17T15:34:13.187Z

the main job grafter does is coerce that gunk into proper values

ghadi 2019-05-17T15:34:29.187400Z

the compiler will just give up and emit reflective code

2019-05-17T15:35:01.187900Z

but the code runs at compile-time

ghadi 2019-05-17T15:35:18.188400Z

oh yeah - true

alexmiller 2019-05-17T15:54:14.189100Z

I retract my worry

2019-05-17T16:04:15.189700Z

the only emoji completion for phew is :christopher_walken:

1
2019-05-17T19:02:32.192300Z

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-holding

2019-05-17T19:04:37.194500Z

the 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

2019-05-17T19:04:55.194800Z

is this really happening because it sounds too fancy to be true

2019-05-17T19:08:35.195Z

I dunno maybe it isn't

2019-05-17T19:08:56.195400Z

I guess it just never occurred to me that the jvm could tell a function was being called for the last time

2019-05-17T20:58:32.197900Z

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.

👍 1
2019-05-17T21:21:49.198600Z

I think it is entirely possible it is just locals clearing, but you would want to look at the bytecode to be sure

2019-05-17T21:22:49.199Z

the clojure compiler can't know the function is only going to be called once

2019-05-17T21:22:57.199300Z

if it might be called again, you have to hold onto the head, just in case