Единственный способ, которым Класс может быть выгружен, это если используемый Classloader является сборщиком мусора. Это означает, что ссылки на каждый отдельный класс и на самого загрузчика классов должны идти по пути додо.
Одним из возможных решений вашей проблемы является наличие Classloader для каждого jar-файла и Classloader для каждого из AppServers, который делегирует фактическую загрузку классов определенным загрузчикам классов Jar. Таким образом, вы можете указать разные версии файла JAR для каждого сервера приложений.
Это не тривиально, хотя. Платформа OSGi стремится сделать именно это, так как каждый пакет имеет свой загрузчик классов и зависимости определяются платформой. Возможно, хорошим решением было бы взглянуть на это.
Если вы не хотите использовать OSGI, одной из возможных реализаций может быть использование одного экземпляра класса JarClassloader для каждого файла JAR.
И создайте новый класс MultiClassloader, который расширяет Classloader. Этот класс внутренне будет иметь массив (или List) JarClassloaders, а в методе defineClass () будет перебирать все внутренние загрузчики классов до тех пор, пока не будет найдено определение или не будет сгенерировано исключение NoClassDefFoundException. Для добавления новых классов JarClassloaders в класс может быть предоставлена пара методов доступа. Существует несколько возможных реализаций в сети для MultiClassLoader, поэтому вам даже не нужно писать свой собственный.
Если вы создаете экземпляр MultiClassloader для каждого соединения с сервером, в принципе возможно, что каждый сервер использует разные версии одного и того же класса.
Я использовал идею MultiClassloader в проекте, где классы, которые содержали пользовательские сценарии, должны были загружаться и выгружаться из памяти, и это работало довольно хорошо.