Ответ 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, и этот вкус еще больше.