Java: ¿cómo cargar diferentes versiones de la misma clase?

He leído mucho sobre los cargadores de clases de Java, pero hasta ahora no he podido encontrar una respuesta para esta simple pregunta:

Tengo dos versiones de com.abc.Hello.class en jar v1.jar y v2.jar . Quiero usar ambos en mi aplicación. ¿Cuál es la forma más simple de hacer esto?

No espero ser tan simple, pero algo en esta línea sería increíble:

Classloader myClassLoader = [magic that includes v1.jar and ignores v2.jar] Hello hello = myclassLoader.load[com.abc.Hello] 

Y en una clase diferente:

 Classloader myClassLoader = [magic that includes v2.jar and ignores v1.jar] Hello hello = myclassLoader.load[com.abc.Hello] 

Me gustaría evitar el uso de OSGi.

Estás yendo por el camino correcto. Debes tomar algunas cosas en cuenta.

Lo normal es que se usen las clases que existen en los cargadores de clase padre. Entonces, si quieres dos versiones, esas clases no deben estar allí.

Pero si desea interactuar, puede usar la reflexión, o incluso mejor, una interfaz común. Entonces haré esto:

 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(); 

Usted casi ha escrito la solución. Espero que el siguiente fragmento de código ayude.

 ClassLoader cl = new URLClassLoader(new URL[] {new File("v1.jar").toURL()}, Thread.currentThread().getContextClassLoader()); Class< ?> clazz = cl.loadClass("Hello"); 

Reemplace v1.jar por v2.jar y este código cargará la versión # 2.

depende de qué vas a hacer con ambas versiones y cómo, pero en general puedes al menos cargar 2 versiones de clase en diferentes cargadores de clases, y luego configurar Thread.contextClassloader () y jugar …

ver http://www.javaworld.com/javaqa/2003-06/01-qa-0606-load.html y http://docs.oracle.com/javase/jndi/tutorial/beyond/misc/classloader.html

Para una implementación de muestra de la respuesta aceptada, @helios checkout github.com/atulsm/ElasticsearchClassLoader