I'm REPLed in to a running service, and have a var pointing to a classloader with which a plugin was loaded (with my.package installed).
The DynamicClassLoader used by the REPL does not include the plugin with which I wish to interact; I wish to be able to work with classes loaded from the plugin despite this limitation.
The following works:
=> (.loadClass plugin-classloader "my.package.MyClass")
my.package.MyClass
...whereas the following doesn't (explicitly overriding the thread context classloader):
=> (do
(.setContextClassLoader (Thread/currentThread) plugin-classloader)
(Class/forName "my.package.MyClass"))
ClassNotFoundException my.package.MyClass java.net.URLClassLoader$1.run (URLClassLoader.java:202)
...and neither does this (explicitly overriding the thread context classloader and the clojure.lang.Compiler/LOADER reference):
=> (let [dcl (clojure.lang.DynamicClassLoader. plugin-classloader)]
(.setContextClassLoader (Thread/currentThread) dcl)
(with-bindings* {clojure.lang.Compiler/LOADER dcl}
(eval '(pr-str (Class/forName "my.package.MyClass")))))
ClassNotFoundException my.package.MyClass java.net.URLClassLoader$1.run (URLClassLoader.java:202)
...and neither does this:
=> my.package.MyClass
CompilerException java.lang.ClassNotFoundException: my.package.MyClass, compiling:(NO_SOURCE_PATH:0)
Shouldn't Class.forName() use the thread context classloader when set? I'm trying to make some calls into 3rd-party code doing introspection magic; the tools in question are failing with ClassNotFoundExceptions even when the thread context classloader should be set.
In the case where I'm explicitly setting the context classloader, the stack trace demonstrates that Clojure's DynamicClassLoader (rather than the BundleClassLoader in the plugin-classloader var) is in use:
=> (e)
java.lang.ClassNotFoundException: my.package.MyClass
at java.net.URLClassLoader$1.run (URLClassLoader.java:202)
java.security.AccessController.doPrivileged (AccessController.java:-2)
java.net.URLClassLoader.findClass (URLClassLoader.java:190)
clojure.lang.DynamicClassLoader.findClass (DynamicClassLoader.java:61)
java.lang.ClassLoader.loadClass (ClassLoader.java:306)
java.lang.ClassLoader.loadClass (ClassLoader.java:247)
java.lang.Class.forName0 (Class.java:-2)
java.lang.Class.forName (Class.java:169)
evalis playing some trick there... can you try same thing in compiled clojure code?DynamicClassLoaderinstance bound toclojure.lang.Compiler/LOADERwhenclojure.lang.Compiler/evalis called matters.