Open jpmonettas opened 7 months ago
Maybe we could somehow provide a banlist of packages which class-info should skip?
Maybe we could somehow provide a banlist of packages which class-info should skip?
Yes, please refer to https://github.com/clojure-emacs/orchard/pull/235#issuecomment-2049995452 for the suggested approach
If that's too much of an ask, we can also hardcode that specific class for now - that class never works anyway so a more comprehensive fix would be superset of the smaller fix.
Thanks!
Maybe we can hardcode skip the javafx package and go for a more general solution if there is ever another problem with this? I feel it is a super niche issue to introduce a new file. Wdyt?
I don't know - there are all sorts of exotic Java classes so a file would seem best to me.
That, or a System property edn-encoding a list of classes, but it would seem cumbersome.
So list of classes wouldn't work unless they are prefixes of some kind. On javafx for example almost any class can break it (any control class at least)
it seems fine to accept packages and classes, separately
e.g. orchard.edn with {:class-info-banlist {:classes ,,, :packages ,,,}}
I figured that for JavaFX adding dev/user.clj with :
(ns user
(:import [javafx.application Platform]))
(Platform/startup (fn [] (println "JavaFX toolkit initialized")))
solves this issue. Which is a better solution for me than banning it since I get the class info for all javafx packages and classes.
Awesome!
Let's leave this issue open for a while since users can encounter it independently and it won't be obvious to them what's going on.
Suggestions welcome.
Are all cider+flowstorm users affected?
Perhaps we should also document the JavaFX workaround in the README (e.g. under "Caveats")?
Are all cider+flowstorm users affected?
This wasn't affecting FlowStorm users, just developing FlowStorm with the latest cider was crashing.
Perhaps we should also document the JavaFX workaround in the README (e.g. under "Caveats")?
Yes. Although it's also true that cider-nrepl breaks altogether, which we should prevent from happening in the first place.
If we don't come up with something better (e.g. dyamically, non-obstrusively detecting whether Javafx has been initialized), I'd prevent analysis of that package unless the user has said it has initialized it (e.g. pass a System prop, as a hint that initialization is there).
Maybe we can try slurp
ing user.clj but it would be pretty dubious ðŸ¤
I don't know if we should invest too much efforts into this given how niche JavaFX is these days. Might be easiest to just hardcode a workaround for this or something along those lines.
If I understand correctly, the problem happens because cider-nrepl tries to initialize classes that the user didn't ask it to. Regardless of whether JavaFX is to blame here, I can imagine other instances where the user wouldn't want classes being initialized out of order, and passing false
to Class/forName
is not a reliable safety net (as demonstrated by this issue).
So, how important warming those caches is? If it only costs +0.5 seconds for the user on first access versus potentially breaking something, I'd say that this UX optimization is not worth it. Or, at least, limit the warmup to JDK base and Clojure classes. Or is there something else that will stop working if the warmup doesn't happen?
Hi, sorry, I'd really appreciate the discussion not going off rails. I've already spent a lot of time leaving this in a usable and performant manner for a wide variety of use cases.
Now all that's being discussed is the flavor of small hardcoding to be applied.
The long-term solution is https://github.com/clojure-emacs/orchard/issues/211 and I have set time in my calendar to specifically work on it May and June.
Thanks - V
I've already spent a lot of time leaving this in a usable and performant manner for a wide variety of use cases.
Just wondering, does it require enrich-classpath
? Because I'm not sure the work that it is supposed to be doing works for me, I have plain-old "Not documented." strings for methods and classes. It's supposed to have javadocs, right?
Yes, without Enrich, Orchard won't have access to javadocs that can be parsed
(btw, Enrich had some bumpy beginnings but I'd encourage you to try it out - I hear good user reports from a variety of people and much fewer bug reports. The inspector also becomes better with those javadocs)
I also hit this when trying to test one of the cljfx examples.
examples/e01_basic.clj
/usr/bin/clojure -Sdeps \{\:deps\ \{nrepl/nrepl\ \{\:mvn/version\ \"1.3.0\"\}\ cider/cider-nrepl\ \{\:mvn/version\ \"0.50.2\"\}\ refactor-nrepl/refactor-nrepl\ \{\:mvn/version\ \"3.10.0\"\}\}\ \:aliases\ \{\:cider/nrepl\ \{\:main-opts\ \[\"-m\"\ \"nrepl.cmdline\"\ \"--middleware\"\ \"\[refactor-nrepl.middleware/wrap-refactor\,cider.nrepl/cider-middleware\]\"\]\}\}\} -M:cider/nrepl:examples
(appended :examples
to the end)(ns e01-basic (:require [cljfx.api :as fx]))
The exception seems to indicate that JavaFX does not like to be initialized on a thread which is not the "event thread":
Exception in thread "JavaFX Application Thread" java.lang.NoClassDefFoundError: Could not initialize class javafx.stage.Screen
at com.sun.javafx.tk.quantum.QuantumToolkit.initSceneGraph(QuantumToolkit.java:331)
at com.sun.javafx.tk.quantum.QuantumToolkit.runToolkit(QuantumToolkit.java:374)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$startup$10(QuantumToolkit.java:290)
at com.sun.glass.ui.Application.lambda$run$1(Application.java:155)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:316)
at java.base/java.lang.Thread.run(Thread.java:1570)
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.IllegalStateException: This operation is permitted on the event thread only; currentThread = clojure-agent-send-off-pool-0 [in thread "clojure-agent-send-off-pool-0"]
at com.sun.glass.ui.Application.checkEventThread(Application.java:447)
at com.sun.glass.ui.Screen.setEventHandler(Screen.java:367)
at com.sun.javafx.tk.quantum.QuantumToolkit.setScreenConfigurationListener(QuantumToolkit.java:724)
at javafx.stage.Screen.<clinit>(Screen.java:74)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:413)
at java.base/java.lang.Class.forName(Class.java:404)
at orchard.java$class_info_STAR_$fn__5437.invoke(java.clj:335)
at orchard.java$class_info_STAR_.invokeStatic(java.clj:334)
at orchard.java$class_info_STAR_.invoke(java.clj:330)
at orchard.java$class_info.invokeStatic(java.clj:387)
at orchard.java$class_info.invoke(java.clj:379)
at cider.nrepl$warmup_orchard_caches_BANG_.invokeStatic(nrepl.clj:71)
at cider.nrepl$warmup_orchard_caches_BANG_.invoke(nrepl.clj:53)
at cider.nrepl$fn__6246.invokeStatic(nrepl.clj:77)
at cider.nrepl$fn__6246.invoke(nrepl.clj:76)
at clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)
at clojure.lang.AFn.call(AFn.java:18)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.ut
Adding a user.clj
to the classpath which pre-initializes JavaFX as described in https://github.com/clojure-emacs/orchard/issues/250#issuecomment-2074925678 solves the issue.
Currently you can't develop JavaFX applications with the latest versions of Cider because orchard.java/class-info tries to initialize JavaFX classes without the toolkit already initialized. More of a problem is that initializing any JavaFX class before the toolkit has been initialized breaks JavaFX state, so just catching the Exception leaves the system broken.
Changing that line into :
so it doesn't initialize the class doesn't fix the issue, because there is code further down the road that will "touch" the class and initialize it anyway.
Here is a minimal repo with instructions that doesn't run with Cider https://github.com/jpmonettas/cider-nrepl-bug-repro/