2017 年第 4 四半期の更新: vda8888によって以下にコメントされているように、Java 9 では、システムはもはや.java.lang.ClassLoader
java.net.URLClassLoader
「Java 9 移行ガイド: 最も一般的な 7 つの課題」を参照してください。
今説明したクラス・ローディング戦略は新しいタイプで実装され、Java 9 ではアプリケーション・クラス・ローダーがそのタイプです。
つまりURLClassLoader
、これはもはや ではないため、時折の(URLClassLoader) getClass().getClassLoader()
または(URLClassLoader) ClassLoader.getSystemClassLoader()
シーケンスは実行されなくなります。
java.lang.ModuleLayerは、(クラスパスではなく)モジュールパスに影響を与えるために使用される代替アプローチです。たとえば、「Java 9 モジュール - JPMS の基本」を参照してください。
Java 8 以下の場合:
一般的なコメント:
システムクラスパスを変更することはできません (動作が保証されている移植可能な方法で、以下を参照)。代わりに、新しい ClassLoader を定義する必要があります。
ClassLoader は階層的に機能します...そのため、クラス X への静的参照を作成するクラスは、X と同じ ClassLoader または子 ClassLoader にロードする必要があります。カスタム ClassLoader を使用して、システム ClassLoader リンクによってロードされたコードを適切に作成することはできません。そのため、見つけた追加のコードに加えて、カスタム ClassLoader でメイン アプリケーション コードを実行するように調整する必要があります。
(そうは言っても、この拡張の 例のコメントでクラックされたすべての言及があります)URLClassLoader
また、独自の ClassLoader を作成するのではなく、代わりに URLClassLoader を使用することを検討することもできます。親クラスローダーの URL にないURL で URLClassLoader を作成します。
URL[] url={new URL("file://foo")};
URLClassLoader loader = new URLClassLoader(url);
より完全な解決策は次のとおりです。
ClassLoader currentThreadClassLoader
= Thread.currentThread().getContextClassLoader();
// Add the conf dir to the classpath
// Chain the current thread classloader
URLClassLoader urlClassLoader
= new URLClassLoader(new URL[]{new File("mtFile").toURL()},
currentThreadClassLoader);
// Replace the thread classloader - assumes
// you have permissions to do so
Thread.currentThread().setContextClassLoader(urlClassLoader);
JVM システム クラスローダーが URLClassLoader であると想定する場合 (すべての JVM に当てはまるとは限りません)、リフレクションを使用して実際にシステム クラスパスを変更することもできます... (ただし、これはハックです;)):
public void addURL(URL url) throws Exception {
URLClassLoader classLoader
= (URLClassLoader) ClassLoader.getSystemClassLoader();
Class clazz= URLClassLoader.class;
// Use reflection
Method method= clazz.getDeclaredMethod("addURL", new Class[] { URL.class });
method.setAccessible(true);
method.invoke(classLoader, new Object[] { url });
}
addURL(new File("conf").toURL());
// This should work now!
Thread.currentThread().getContextClassLoader().getResourceAsStream("context.xml");