Java 内で CLASSPATH を変更するにはどうすればよいですか?
質問
Java プロセス内から Java プロセスの CLASSPATH を変更するにはどうすればよいですか?
あなたが私に「なぜあなたはそれをしたいのですか?」と尋ねる前にすぐに説明します。
Clojure REPL を実行している場合、CLASSPATH にさらに多くの jar をロードする必要があるのが一般的です。 クロージュア Clojure 自体を再起動せずに実行したいと考えています (これは、Emacs 上の Slime で使用する場合には実際には選択肢ではありません)。
それが理由ですが、私はこの質問が「変な言語」「変なエディタ」というタグ付けされて、答えを持っているかもしれない大多数の Java 開発者に無視されることを望みません。
解決
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 を定義する必要があります。
クラスローダーは階層的な方法で動作します...したがって、クラス X への静的参照を行うクラスは、X と同じ ClassLoader または子 ClassLoader にロードする必要があります。以前にそうしなかった場合、カスタム ClassLoader を使用してシステム ClassLoader リンクによってコードを適切にロードすることはできません。したがって、見つけた追加コードに加えて、メイン アプリケーション コードがカスタム ClassLoader で実行されるように手配する必要があります。
(そうは言っても、 ひび割れたすべて コメントでこの例について言及しています を延長する URLClassLoader
)
また、独自の ClassLoader を作成せず、代わりに URLClassLoader を使用することを検討することもできます。次の URL を使用して URLClassLoader を作成します。 ない 親クラスローダーの URL 内。
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");
他のヒント
あなたができるとは思わない-正しいこと(私は信じる)は、新しいパスで新しいクラスローダーを作成することだ。あるいは、クラスパス(ローダーの)を動的に変更できる独自のクラスローダーを作成することもできます。
を使用して調べることができます。 java.net.URLClassLoader 。元々クラスパスになかったクラスをプログラムでロードすることができますが、それが正確に必要かどうかはわかりません。
以下の2つのリンクからわかるように、VonCが提供する方法が最適と思われますが、これらの投稿のいくつかを確認し、「Java Dynamic Classpath」をグーグルで検索してください。または" Java Dynamic Class Loading"そこからいくつかの情報を見つけます。
より詳細に投稿しますが、VonCはほとんど仕事をしました。
サンフォーラムの投稿も確認してください。
String s="java -classpath abcd/ "+pgmname+" "+filename;
Process pro2 = Runtime.getRuntime().exec(s);
BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream()));
は、Javaプログラムでクラスパスを変更する例です