La única forma en que una clase se puede descargar es si el cargador de clases utilizado es recolección de basura. Esto significa que las referencias a cada clase y al cargador de clases en sí deben seguir el camino del dodo.
Una posible solución a su problema es tener un cargador de clases para cada archivo jar y un cargador de clases para cada uno de los servidores de aplicaciones que delegue la carga real de clases a cargadores de clases Jar específicos. De esa manera, puede apuntar a diferentes versiones del archivo jar para cada servidor de aplicaciones.
Sin embargo, esto no es trivial. La plataforma OSGi se esfuerza por hacer exactamente esto, ya que cada paquete tiene un cargador de clases diferente y las dependencias son resueltas por la plataforma. Tal vez una buena solución sería echarle un vistazo.
Si no desea utilizar OSGI, una posible implementación podría ser utilizar una instancia de la clase JarClassloader para cada archivo JAR.
Y cree una nueva clase MultiClassloader que amplíe Classloader. Esta clase internamente tendría una matriz (o Lista) de JarClassloaders, y en el método defineClass () iteraría a través de todos los cargadores de clase internos hasta que se pueda encontrar una definición, o se arroje una NoClassDefFoundException. Se pueden proporcionar un par de métodos de acceso para agregar nuevos JarClassloaders a la clase. Hay varias implementaciones posibles en la red para un MultiClassLoader, por lo que es posible que ni siquiera necesite escribir el suyo.
Si instancia un MultiClassloader para cada conexión al servidor, en principio es posible que cada servidor use una versión diferente de la misma clase.
Utilicé la idea de MultiClassloader en un proyecto, donde las clases que contenían scripts definidos por el usuario tenían que cargarse y descargarse de la memoria y funcionaban bastante bien.