Порядок загрузки jar-файлов из каталога lib
Может ли кто-нибудь объяснить порядок загрузки jar-файлов из каталога lib в Tomcat? Это по алфавиту? Случайные? Или какой-то другой заказ?
4 ответа
Это все описано в TomLow ClassLoading HOW-TO. Это не обязательно в алфавитном порядке. Если вы наблюдали такое поведение, на него абсолютно не следует полагаться, если вы намерены поддерживать переносимость вашего веб-приложения на серверах. Например, Tomcat 6 "по совпадению" заказывает его, а Tomcat 8 - нет.
В итоге порядок загрузки выглядит следующим образом:
- начальная загрузка / система (
JRE/lib
, затемserver.loader
) - библиотеки веб-приложений (
WEB-INF/classes
, затемWEB-INF/lib
) - общие библиотеки (
common.loader
, затемTomcat/lib
) - библиотеки общего доступа к веб-приложениям (
shared.loader
)
Если вы хотите гарантировать, что JAR X будет загружен после JAR Y, вам нужно будет поместить JAR X в одно из мест, которое появится позже в приведенном выше листинге.
Однако есть исключения, которые упоминаются в документации по tomcat.
Наконец, загрузчик классов веб-приложений всегда сначала делегирует классы API JavaEE для спецификаций, реализованных Tomcat (Servlet, JSP, EL, WebSocket). Все остальные загрузчики классов в Tomcat следуют обычному шаблону делегирования.
Это означает, что если веб-приложение содержит какие-либо классы JavaEE (javax.*
), то он будет игнорироваться котом.
Для каждого загрузчика классы просто загружаются JVM в том порядке, в котором они должны быть импортированы / выполнены и еще не загружены.
На самом деле, это в алфавитном порядке! (Внутри определенного каталога, например, каталога 'lib', который упоминает оригинальный автор.)
Более конкретно, если вы посмотрите на источник для Tomcat 6, в классе FileDirContext
, метод list()
звонки Arrays.sort()
на массиве имен файлов jar, которые найдены.
Я также проверил это вручную. Я создаю войну с JSP, который призывает HelloWorld.getGreeting()
и поместите две почти идентичные банки, содержащие немного разные версии HelloWorld
в каталог WEB-INF/lib. Один говорит "Привет, мир", другой - "До свидания, жестокий мир".
Если я назову версию "Hello, world" a.jar, а версию "goodbye" b.jar и перезапущу Tomcat, я получу текст "Hello". Если я назову банки в обратном порядке и перезапущу Tomcat, я получу текст "До свидания".
Насколько я смог определить, это поведение НЕ задокументировано, НЕ указано и на него НЕ следует полагаться. Но это по алфавиту - пока.
Заказ на загруженные банки в папке WEb-INF/lib.
Для кота 5-7 порядок в алфавитном порядке. Он использует сортировку.
Для tomcat 8 случайное решение определяется базовой файловой системой.
Я полностью согласен с ответом, предоставленным BalusC. Единственное, что нужно добавить, это то, что когда загружается JAR из соответствующего загрузчика классов, он проверяет алфавитный порядок.
У меня была ситуация для загрузки "XSSFWorkbook" в мое веб-приложение для чтения данных из таблицы Excel, и у меня было два JARS "poi-ooxml-3.9.jar" и "org.eclipse.birt.runtime_4.3.1.v20130918-1142.jar" с тем же именем класса и структурой пакета. Я просто восстановил позже, так что в алфавитном порядке идет рядом с более ранним, и это помогло мне. Просто хотел поделиться тем же.
Удачи
В нашей среде WebSphere разные машины загружают банку в разном порядке. Поэтому я согласен с user2193008. Мы сталкиваемся с проблемой загрузчика классов в производственной среде, где тот же код отлично работает в более низкой среде. Мы исправили проблему, удалив дубликат jar в lib, например, есть две версии spring jar, spring_v1.jar и spring_v2.jar, если classloader загружает сначала v1, код работает нормально, но если classloader загружает сначала v2, проблема.