Как Tomcat Classloader разделяет разные области объекта Webapps в одной и той же JVM?

Так как Tomcat может загружать более одного веб-приложения одновременно, эти веб-приложения могут работать отдельно и не мешать друг другу, и они работают в одной и той же JVM. Поэтому я очень озадачен тем, как Tomcat обрабатывает область действия Object в той же JVM.

Например, у меня есть одноэлементный объект в обоих разных веб-приложениях, и tomcat сгенерирует два разных одноэлементных объекта для каждого. Я всегда думал, что у одноэлементного объекта есть только один объект в той же JVM, но в tomcat JVM может быть два или более.


Я прочитал некоторую информацию о ClassLoader, Tomcat имеет свой собственный WebAppClassLoader для загрузки веб-приложений. Значит ли это, что Object Scope здесь - это ClassLoader или я ошибаюсь. Кто-нибудь знает об этом или может дать мне некоторую информацию о макете рабочей памяти tomcat?

Ответ 1

Все секреты скрыты за этими ClassLoader экземплярами.

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

Таким образом, если класс загружается двумя различными загрузчиками классов, этот класс существует дважды внутри виртуальной машины, он имеет два набора статических полей, может иметь разный байтовый код (например, разные реализации методов) и все такое. Обратите внимание, что эти два объекта нельзя привести друг к другу, даже если их имена идентичны. "Нормальные" Java-приложения имеют все классы, загруженные иерархией загрузчика классов, и каждый класс загружается только один раз.

Для более сложных сценариев вам понадобится другое поведение. Иногда вы хотите изолировать библиотеку от работы с вашим кодом (например, плагины в eclipse или веб-приложения на сервере приложений).

Основная идея изолировать вашу программу от других классов состоит в том, чтобы загрузить те с дополнительным загрузчиком классов и использовать много размышлений. Если вы хотите прочитать об этом, посмотрите документацию Oracle на ClassLoaders или OSGI.

Tomcat (и многие другие веб-контейнеры/серверы приложений) загружают приложение с отдельными иерархиями ClassLoader. Это изолирует все классы от других (веб) приложений и, таким образом, также гарантирует, что синглтоны, разные версии классов и все эти вещи не сталкиваются.

Ответ 2

Помните, что класс в Java идентифицируется его полностью определенным именем и загрузчиком классов, который его загрузил. Tomcat использует отдельные загрузчики классов для каждого развертываемого вами контекста (веб-приложения), что позволяет хранить их отдельно. Кроме того, системный загрузчик классов загружает специфичные для tomcat библиотеки, а загрузчик JVM загружает базовые библиотеки Java.

Ответ 3

Одна вещь, которая всегда забывается при разговоре о синглонах, заключается в том, что singleton может иметь только один экземпляр для каждого загрузчика классов. A ClassLoader ограничивает видимость класса, поэтому один и тот же класс может существовать под несколькими разными загрузчиками классов в той же виртуальной машине. Это позволяет, помимо прочего, иметь разные версии загружаемых банок одновременно.

Этот вопрос: Java Class Loaders, похоже, содержит интересные ссылки и ресурсы для дальнейшего изучения.

Ответ 4

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

Для серверов веб-приложений это немного отличается. Как правило, существуют разные загрузчики классов для каждого веб-приложения, развернутого на сервере веб-приложений, таком как tomcat. Для Tomcat это выглядит ниже -

enter image description here

Таким образом, для веб-приложений загрузка классов происходит в следующем порядке -

  1. Начальные классы вашей JVM (базовые Java-классы)
  2. /WEB-INF/классы вашего веб-приложения
  3. /WEB-INF/lib/*.jar вашего веб-приложения
  4. Классы системного загрузчика классов (классы Tomcat/Classpath)
  5. Общие классы загрузчиков классов (классы, общие для всех веб-приложений)

Но обратите внимание, если загрузчик классов веб-приложений настроен с delegate="true", то порядок меняется -

  1. Начальные классы вашей JVM (базовые Java-классы)
  2. Классы системного загрузчика классов (классы Tomcat/Classpath)
  3. Общие классы загрузчиков классов (классы, общие для всех веб-приложений)
  4. /WEB-INF/классы вашего веб-приложения
  5. /WEB-INF/lib/*.jar вашего веб-приложения

Более подробную информацию вы можете найти на странице Apache Tomcat Class Loader HOW-TO.

Ответ 5

"ID" класса в JVM состоит из полного имени класса и загрузчика классов, который использовался для его загрузки. Это означает, что если вы загружаете два класса с одинаковым именем разными загрузчиками классов, они считаются разными классами.

Ответ 6

Таким образом, singleton будет singleton для загрузчика классов - в контейнере /JVM; поскольку контейнер /JVM может иметь несколько загрузчиков классов.

Ответ 7

  • Другое приложение в tomcat, использующее разный загрузчик классов для разделения. Например, app1, используя ClassLoaderA, app2, используя classloaderB.
  • Каждый класс будет использовать свой собственный загрузчик классов для загрузки других классов. Поэтому, если ClassA.class ссылается на ClassB.class, тогда ClassB должен находиться в пути к классам загрузчика классов ClassA или его родителей. Например, в app1, com.exmaple.test1 загружается из ClassLoaderA. И com.exmaple.test1 хотите новый com.exmaple.test2(). По умолчанию он использует свой собственный загрузчик классов ClassLoaderA для загрузки com.exmaple.test2. Таким образом, в представлении com.exmaple.test1 он может видеть только свой класс classpath (app1/webapp/classes или app1/webapp/lib). И в app2 он увидит другое представление.
  • В резюме learnloader вы должны понимать модель делегирования. И видимость заключается в том, что ребенок может видеть родителя. но родитель не может видеть ребенка, и родной брат не может видеть родного брата. Таким образом, мы можем изолировать различные приложения.

Ответ 8

В наше время мы используем все больше и больше Springboot. И приложение может работать со встроенным причалом или котом или другими контейнерами. Можем ли мы сказать, что пользовательский загрузчик классов tomcat, который использовался для разделения веб-приложений, устарел?