Javaクラスローダーについてたくさん読んだことがありますが、これまでのところ、この簡単な質問に対する答えを見つけることができませんでした:
Jarにcom.abc.Hello.classの2つのバージョンがあるv1.jarおよびv2.jar。アプリケーションで両方を使用したい。これを行う最も簡単な方法は何ですか?
私はそんなに単純であるとは思っていませんが、これらの線に沿った何かが素晴らしいでしょう:
Classloader myClassLoader = [magic that includes v1.jar and ignores v2.jar]
Hello hello = myclassLoader.load[com.abc.Hello]
そして別のクラスで:
Classloader myClassLoader = [magic that includes v2.jar and ignores v1.jar]
Hello hello = myclassLoader.load[com.abc.Hello]
OSGiの使用を避けたい。
あなたは正しい道を進んでいます。あなたはいくつかのことを考慮に入れなければなりません。
通常は、親クラスローダーに存在するクラスが使用されます。したがって、2つのバージョンが必要な場合は、それらのクラスが存在してはなりません。
ただし、やり取りしたい場合は、リフレクションを使用するか、共通インターフェースを使用することもできます。だから私はこれをやります:
common.jar:
BaseInterface
v1.jar:
SomeImplementation implements BaseInterface
v2.jar:
OtherImplementation implements BaseInterface
command-line:
Java -classpath common.jar YourMainClass
// you don't put v1 nor v2 into the parent classloader classpath
Then in your program:
loader1 = new URLClassLoader(new URL[] {new File("v1.jar").toURL()}, Thread.currentThread().getContextClassLoader());
loader2 = new URLClassLoader(new URL[] {new File("v2.jar").toURL()}, Thread.currentThread().getContextClassLoader());
Class<?> c1 = loader1.loadClass("com.abc.Hello");
Class<?> c2 = loader2.loadClass("com.abc.Hello");
BaseInterface i1 = (BaseInterface) c1.newInstance();
BaseInterface i2 = (BaseInterface) c2.newInstance();
あなたはほとんど解決策を書きました。次のコードがお役に立てば幸いです。
ClassLoader cl = new URLClassLoader(new URL[] {new File("v1.jar").toURL()}, Thread.currentThread().getContextClassLoader());
Class<?> clazz = cl.loadClass("Hello");
置換v1.jar
沿って v2.jar
そしてこのコードはバージョン#2をロードします。
@heliosチェックアウトで受け入れられた回答のサンプル実装について github.com/atulsm/ElasticsearchClassLoader
それは両方のバージョンでどのように処理するかと方法に依存しますが、一般的には、少なくとも2つのバージョンのクラスを異なるクラスローダーにロードしてから、Thread.contextClassloader()そしてプレイ...
http://www.javaworld.com/javaqa/2003-06/01-qa-0606-load.html および http://docs.Oracle.com/javase/を参照してくださいjndi/tutorial/beyond/misc/classloader.html