実行中のサービスに REPL されており、プラグインがロードされた (インストール済みの) クラスローダーを指す var がありますmy.package
。
REPL で使用される DynamicClassLoader には、対話したいプラグインが含まれていません。この制限にもかかわらず、プラグインからロードされたクラスを操作できるようにしたいと考えています。
以下の作品:
=> (.loadClass plugin-classloader "my.package.MyClass")
my.package.MyClass
...一方、以下はそうではありません(スレッドコンテキストクラスローダーを明示的にオーバーライドします):
=> (do
(.setContextClassLoader (Thread/currentThread) plugin-classloader)
(Class/forName "my.package.MyClass"))
ClassNotFoundException my.package.MyClass java.net.URLClassLoader$1.run (URLClassLoader.java:202)
...そしてどちらもこれを行いません (スレッドコンテキストクラスローダーとclojure.lang.Compiler/LOADER 参照を明示的にオーバーライドします):
=> (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)
...そしてどちらもこれをしません:
=> my.package.MyClass
CompilerException java.lang.ClassNotFoundException: my.package.MyClass, compiling:(NO_SOURCE_PATH:0)
Class.forName()
設定時にスレッド コンテキスト クラスローダを使用しないでください。イントロスペクション マジックを実行するサードパーティ コードを呼び出しようとしています。問題のツールは、スレッド コンテキスト クラスローダーを設定する必要がある場合でも ClassNotFoundExceptions で失敗します。
コンテキスト クラスローダーを明示的に設定している場合、スタック トレースは、Clojure の DynamicClassLoader (プラグイン クラスローダー変数の BundleClassLoader ではなく) が使用されていることを示しています。
=> (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)