Java - как загрузить разные версии одного и того же класса?
Я много читал о загрузчиках классов Java, но до сих пор мне не удалось найти ответ на этот простой вопрос:
У меня есть две версии com.abc.Hello.class в банках 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.
Ответы
Ответ 1
Вы идете правильно. Вы должны учитывать некоторые вещи.
Обычная вещь - классы, которые существуют в родительских загрузчиках классов. Поэтому, если вы хотите две версии, эти классы не должны быть там.
Но если вы хотите взаимодействовать, вы можете использовать отражение или даже лучше общий интерфейс. Поэтому я сделаю это:
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();
Ответ 2
Ты почти написал решение.
Я надеюсь, что следующий фрагмент кода поможет.
ClassLoader cl = new URLClassLoader(new URL[] {new File("v1.jar").toURL()}, Thread.currentThread().getContextClassLoader());
Class<?> clazz = cl.loadClass("Hello");
Замените v1.jar
на v2.jar
, и этот код загрузит версию # 2.
Ответ 3
это зависит от того, что вы собираетесь делать с обеими версиями и как, но в целом вы можете хотя бы загрузить 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
Ответ 4
Для примера реализации принятого ответа с помощью проверки @helios github.com/atulsm/ElasticsearchClassLoader