La seule façon dont une classe peut être déchargée est si le chargeur de classe utilisé est garbage collection. Cela signifie que les références à chaque classe et au chargeur de classe lui-même doivent suivre la voie du dodo.
Une solution possible à votre problème consiste à avoir un Classloader pour chaque fichier jar et un Classloader pour chacun des AppServers qui délègue le chargement réel des classes à des classloaders Jar spécifiques. De cette façon, vous pouvez pointer vers différentes versions du fichier jar pour chaque serveur d'applications.
Ce n'est pas anodin, cependant. La plate-forme OSGi s'efforce de faire exactement cela, car chaque bundle a un chargeur de classe différent et les dépendances sont résolues par la plate-forme. Peut-être qu'une bonne solution serait de l'examiner.
Si vous ne souhaitez pas utiliser OSGI, une implémentation possible pourrait être d'utiliser une instance de la classe JarClassloader pour chaque fichier JAR.
Et créez une nouvelle classe MultiClassloader qui étend Classloader. Cette classe aurait en interne un tableau (ou une liste) de JarClassloaders, et dans la méthode defineClass () itérerait à travers tous les chargeurs de classe internes jusqu'à ce qu'une définition puisse être trouvée, ou qu'une NoClassDefFoundException soit levée. Quelques méthodes d'accès peuvent être fournies pour ajouter de nouveaux JarClassloaders à la classe. Il existe plusieurs implémentations possibles sur le net pour un MultiClassLoader, vous n'aurez donc peut-être même pas besoin d'écrire la vôtre.
Si vous instanciez un MultiClassloader pour chaque connexion au serveur, il est en principe possible que chaque serveur utilise une version différente de la même classe.
J'ai utilisé l'idée de MultiClassloader dans un projet, où les classes contenant des scripts définis par l'utilisateur devaient être chargées et déchargées de la mémoire et cela fonctionnait très bien.