Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

Погрузочная загрузка webapp похожа в принципе, но на практике она намного сложнее. Для конкретного webapp загрузчик классов webapp ищет классы в следующем порядке. Например, Tomcat 6 ищет классы в следующем порядке:

  • Начальные классы вашей JVM
  • Классы загрузчика системного класса (описано здесь)
  • /WEB-INF/классы webapp
  • /WEB-INF/lib/*. jar webapp
  • $CATALINA_HOME/Библиотека
  • $CATALINA_HOME/Library/*. Баночка

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

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

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

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

Followup

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

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

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

Ответ 2

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

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

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

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

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

Ответ 3

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