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

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

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

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

3 ответа

Решение

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

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

  1. Начальные классы вашей JVM
  2. Системные классы загрузчика классов (описано здесь)
  3. / WEB-INF / классы веб-приложения
  4. /WEB-INF/lib/*.jar веб-приложения
  5. $CATALINA_HOME/ Lib
  6. $CATALINA_HOME/ Библиотека / *. Баночка

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

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

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

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

СЛЕДОВАТЬ ЗА

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам