Как работает загрузка класса, когда один и тот же класс существует в разных приложениях на одном и том же сервере?

StackOverflow https://stackoverflow.com/questions/4132545

Вопрос

У меня есть несколько веб-приложений, запущенных на сервере приложений, и каждый файл войны Web-App содержит копию одного и того же файла JAR.

Означает ли это, что класс в этом файле JAR будет загружен несколько раз в JVM, один раз для каждого файла войны, в котором он существует? Следуя этому, если у меня есть статический синхронизированный метод в таком классе, он синхронизируется только среди потоков в веб-приложении, в котором он существует, но не синхронизируется с одним и тем же методом в одном классе в другом файле JAR в другом Военный файл? (Надеюсь, вопрос имеет смысл, будет прояснится, если это необходимо).

Если это так, я предполагаю, что лучшее решение - удалить файл JAR из каждого файла войны и развернуть его в папку общей папки класса на сервере?

Это было полезно?

Решение

Java ClassLoader обычно работает, ища классы в одном или нескольких местах в фиксированной последовательности. Например, ClassLoader, который загружает ваше приложение, когда вы запускаете его из командной строки, выглядит первым в rt.jar Файл (и другие на BootClassPath), а затем в каталогах и файлах JAR, указанных вашим классом.

Загрузка класса WebApp в принципе аналогична, но на практике немного сложнее. Для конкретного веб -приложения классной загрузчик веб -приложения ищет классы в следующем порядке. Например, Tomcat 6 ищет занятия в этом порядке:

  1. Начальная загрузка вашего JVM
  2. Классы загрузчика системного класса (описано здесь)
  3. /Web-inf/классы веб-приложения
  4. /Web-inf/lib/*.jar of the WebApp
  5. $ Catalina_home/lib
  6. $ Catalina_home/lib/*. Jar

Конечно, как только класс -загрузчик нашел класс, который он ищет, он не выглядит дальше. Таким образом, занятия с тем же именем позже в заказе не будут загружены.

Осложнение состоит в том, что веб -контейнер имеет один загрузчик класса для каждого веб -приложения, и эти загрузчики класса делегируют другим загрузчикам класса, которые управляют общими классами. На практике это означает, что некоторые классы будут загружены только один раз для всего контейнера (например, 1. и 2.), а другие могут загружаться несколько раз различными загрузчиками.

(Когда класс загружается более одного раза, он приводит к различным Class Объекты и отдельная статика класса. Версии класса разные типы, что касается JVM, и вы не можете типировать из одной версии к другой.)

Наконец, Tomcat может быть настроен, чтобы позволить отдельным веб -приложениям быть «горячим загруженным». Это влечет за собой остановку веб -приложения, создание нового класса загрузчика и перезапуска его.

СЛЕДОВАТЬ ЗА

Итак ... синхронизация статического метода не будет защищать доступ к общему ресурсу, где класс был загружен несколько раз?

Это зависит от деталей, но, вероятно, не будет. (Или посмотреть, если другой способ, если у класса есть на самом деле был загружен несколько раз, тогда static Метод каждой «загрузки» класса будет получить доступ к другому набору static поля.)

Если вы действительно хотите, чтобы экземпляр класса приложения Singleton был разделен на несколько веб -приложений в одном и том же контейнере, это проще, если вы вкладываете класс в $CATALINA_HOME/lib или эквивалент. Но вы также должны спросить себя, является ли это хорошим дизайном системы. Рассмотрите возможность объединения веб -приложений или использования переадресации запросов и т. Д. Вместо общей структуры данных. Одиночный рисунок имеет тенденцию быть проблематичным в веб -приложениях, и этот вкус еще больше.

Другие советы

Серверы приложений Java EE обычно используют несколько загрузчиков класса для выделения приложений друг от друга, и позволяют развернуть новые версии одного приложения, не влияя на другие приложения.

Вы получаете шаблоны, такие как несколько военных файлов и один файл EJB в ухе с иерархией класса -загрузчиков, каждая война имеет свою собственную.

Это приводит к дублированию, как вы описываете, но это не обязательно плохо. Это означает, что у вас даже могут быть разные версии одних и тех же банок, развернутых в одно и то же время, и это может быть на самом деле беннифицированным, что позволяет постепенно миграцию в новые версии.

Некоторые серверы приложений (WebSphere для Exmaple) имеют явную поддержку концепции общей библиотеки, и я это использую.

Будьте осторожны с тем, чтобы просто забрать банки в произвольные пути классов, вы рискуете дестабилизации самого сервера приложений.

Большинство серверов приложений используют Наиболее специфический вдоль пути имеет приоритет политика. Если у вас есть несколько библиотеков, которые делают то же самое, вы должны подумать о том, чтобы поместить их на сервер приложений Lib (Fe: tomcat_home/lib)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top