Загрузчик классов Java обычно работает, ища классы в одном или нескольких местах в фиксированной последовательности. Например, загрузчик классов, который загружает ваше приложение при запуске из командной строки, сначала ищет в файле rt.jar
(и других в bootclasspath), а затем в каталогах и файлах JAR, указанных вашим classpath.
Загрузка классов веб-приложений в принципе похожа, но на практике немного сложнее. Для конкретного веб-приложения загрузчик классов веб-приложения ищет классы в следующем порядке. Например, Tomcat 6 ищет классы в следующем порядке:
- Начальные классы вашей JVM
- Классы загрузчика системных классов (описано здесь )
- / WEB-INF / классы веб-приложения
- / WEB-INF / lib / *. Jar веб-приложения
- $ CATALINA_HOME / Lib
- $ CATALINA_HOME / Библиотека / *. Баночка
Конечно, как только загрузчик классов найдет искомый класс, он больше не будет смотреться. Таким образом, классы с тем же именем позже в заказе не будут загружены.
Сложность состоит в том, что у веб-контейнера есть один загрузчик классов для каждого веб-приложения, и эти загрузчики классов делегируют другим загрузчикам классов, которые управляют общими классами. На практике это означает, что некоторые классы будут загружаться только один раз для всего контейнера (например, 1. и 2.), а другие могут загружаться несколько раз разными загрузчиками классов.
(Когда класс загружается более одного раза, это приводит к отдельным Class
объектам и разным статическим классам. Версии класса имеют разные типы в том, что касается JVM, и вы не можете выполнить приведение типов из одной версии в др.)
Наконец, Tomcat можно настроить для «горячей загрузки» отдельных веб-приложений. Это влечет за собой остановку веб-приложения, создание для него нового загрузчика классов и его перезапуск.
Followup
Итак ... синхронизация статического метода не защитит доступ к общему ресурсу, где класс был загружен несколько раз?
Это зависит от деталей, но, вероятно, не будет. (Или, если посмотреть по-другому, если класс на самом деле был загружен несколько раз, то метод static
каждой "загрузки" класса будет обращаться к другому набору static
полей. )
Если вы действительно хотите, чтобы экземпляр класса одиночного приложения совместно использовался несколькими веб-приложениями в одном контейнере, проще всего поместить класс в $CATALINA_HOME/lib
или его эквивалент. Но вы также должны спросить себя, хороший ли это дизайн системы. Рассмотрите возможность объединения веб-приложений или использования переадресации запросов и т. Д. Вместо общей структуры данных. Шаблон синглтона может быть проблематичным в веб-приложениях, и этот аромат тем более.