Порядок загрузки файлов JAR из каталога lib - PullRequest
36 голосов
/ 29 марта 2011

Может ли кто-нибудь объяснить порядок загрузки jar-файлов из каталога lib в Tomcat? Это по алфавиту? Случайным образом? Или какой-то другой заказ?

Ответы [ 5 ]

36 голосов
/ 29 марта 2011

Это все описано в Tomcat's ClassLoading HOW-TO . Это не обязательно в алфавитном порядке. Если вы наблюдали такое поведение, на абсолютно не следует полагаться , если вы намерены поддерживать переносимость вашего веб-приложения на серверах. Например, Tomcat 6 «случайно» заказывает его, а Tomcat 8 - нет.

В итоге, порядок загрузки выглядит следующим образом:

  1. начальная загрузка / система (JRE/lib, затем server.loader)
  2. библиотеки веб-приложений (WEB-INF/classes, затем WEB-INF/lib)
  3. общие библиотеки (common.loader, затем Tomcat/lib)
  4. библиотеки общего доступа к веб-приложениям (shared.loader)

Если вы хотите гарантировать, что JAR X загружен после JAR Y, то вам нужно поместить JAR X в одно из мест, которое появляется позже в списке выше.

Однако есть исключения, которые упомянуты в документах tomcat

Наконец, загрузчик классов веб-приложений всегда сначала делегирует классы JavaEE API для спецификаций, реализованных Tomcat (Servlet, JSP, EL, WebSocket). Все остальные загрузчики классов в Tomcat следуют обычному шаблону делегирования.

Это означает, что если веб-приложение содержит какие-либо классы JavaEE (javax.*), то tomcat будет игнорировать его.

Для каждого загрузчика классы просто загружаются JVM в том порядке, в котором они должны быть импортированы / выполнены и еще не загружены.

32 голосов
/ 26 октября 2011

На самом деле, это это алфавитный порядок! (Внутри определенного каталога, например, каталога 'lib', о котором упоминает оригинальный автор.)

Более конкретно, если вы посмотрите на источник для Tomcat 6, в классе FileDirContext, метод list() вызывает Arrays.sort() для массива имен файлов найденных jar-файлов.

Я также проверял это вручную. Я создаю войну с JSP, которая вызывает HelloWorld.getGreeting(), и помещаю два почти идентичных файла jar, содержащие несколько разные версии HelloWorld, в каталог WEB-INF / lib. Один говорит «Привет, мир», другой - «Прощай, жестокий мир».

Если я назову версию «Hello, world» a.jar, а версию «goodbye» b.jar и перезапущу Tomcat, я получу текст «Hello». Если я назову банки в обратном направлении и перезапущу Tomcat, я получу текст «До свидания».

Насколько я смог определить, это поведение НЕ задокументировано, НЕ указано и НЕ НАДО полагаться. Но по алфавиту - пока.

23 голосов
/ 30 октября 2014

Заказ на загруженные банки в папке WEb-INF / lib.

Для tomcat 5-7 порядок в алфавитном порядке.Используется сортировка.

Для tomcat 8 случайное решение определяется базовой файловой системой.

https://issues.apache.org/bugzilla/show_bug.cgi?id=57129

1 голос
/ 18 июля 2014

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

У меня была ситуация для загрузки "XSSFWorkbook" в мое веб-приложение для чтения данных из таблицы Excel, и у меня было два JARS "poi-ooxml-3.9.jar" и "org.eclipse.birt.runtime_4.3.1.v20130918-1142 .jar "с тем же именем класса и структурой пакета. Я просто восстановил позже, так что в алфавитном порядке идет рядом с более ранним, и это помогло мне. Просто хотел поделиться тем же.

Удачи

0 голосов
/ 27 февраля 2019

В нашей среде WebSphere разные машины загружают банку в разном порядке. Поэтому я согласен с user2193008. Мы сталкиваемся с проблемой загрузчика классов в производственной среде, где тот же код отлично работает в более низкой среде. Мы устранили проблему, удалив дубликат jar в lib, например, есть две версии spring jar, spring_v1.jar и spring_v2.jar, если загрузчик классов загружает сначала v1, код работает нормально, но если загрузчик классов загружает сначала v2, проблема.

...