Подтвердить что ты не робот

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.

4b9b3361

Ответ 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