Как решить эту проблему с загрузкой классов Tomcat?

У меня есть три веб-приложения на моем сервере Tomcat. Я использую ActiveMQ для отправки сообщений между ними. Это сработало, но теперь я пытаюсь обновиться с 5.14 до 5.18 и столкнулся с проблемой загрузки классов.

Чтобы сэкономить на размерах WAR, у меня был jar activemq-all в глобальном каталоге tomcat/lib, и это сработало, когда я работал с 5.14.

Но что теперь происходит с 5.18, так это то, что я получаю ошибку ClassNotFound для класса в jar-файле, который есть во всех файлах war lib:

Вызвано: java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper по адресу org.apache.activemq.broker.jmx.PersistenceAdapterView.(PersistenceAdapterView.java:31) в org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter.doStart(KahaDBPersistenceAdapter.java:235)

Я не очень хорош в загрузке классов, но по какой-то причине кажется, что когда ActiveMQ настраивает постоянство в одном из моих веб-приложений, класс загружается из «центральной» папки lib, а это означает, что он не может использовать класс. что существует в моей войне?

Я этого не понимаю, потому что загрузчик классов, загружающий класс activeMQ, который пытался загрузить ObjectMapper, должен быть моим загрузчиком классов приложения, так почему же он не находит класс ObjectMapper?

Итак, мои вопросы:

  1. Почему мое приложение не может просто использовать все классы в моей войне И в tomcat/lib? Разве это не тот же загрузчик классов, поскольку именно мое приложение запускает загрузку?

  2. Является ли мое единственное решение отправлять каждую войну с классами activeMQ? это работает, я пробовал, но файлы WAR становятся намного больше...

Указатели очень ценятся.

У вас уже есть решение. Почему размер файла WAR является для вас проблемой?

aled 07.05.2024 16:19

Если вы не встраиваете брокер ActiveMQ в тот же процесс виртуальной машины Java, что и Tomcat, вы можете использовать jar activemq-client без полного activemq-all, чтобы уменьшить размер.

Matt Pavlovich 07.05.2024 16:25

На самом деле это не размер файла войны. Если я не ошибаюсь. если каждый загрузчик классов веб-приложений загружает классы, это увеличит потребление памяти? Загрузка их загрузчиком классов tomcat означает, что классы загружаются в память только один раз, а не несколько раз?

Mathias 08.05.2024 08:07
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обратите внимание: это не ошибка ClassNotFound, а ошибка NoClassDefFoundError. Вероятно, потому, что в пути к классам есть две версии одного и того же класса.

Загрузка классов Tomcat объясняется в документации: https://tomcat.apache.org/tomcat-10.0-doc/class-loader-howto.html. В Tomcat задействовано несколько загрузчиков классов:

Как и многие серверные приложения, Tomcat устанавливает различные загрузчики классов (то есть классы, реализующие java.lang.ClassLoader), чтобы позволить различным частям контейнера и веб-приложениям, работающим в контейнере, иметь доступ к различным репозиториям доступных классы и ресурсы. Этот механизм используется для обеспечения функциональности, определенной в Спецификации сервлетов версии 2.4, в частности, разделах 9.4 и 9.6.

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

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

В общем, если вы собираетесь использовать разные версии jar на одном сервере Tomcat, избегайте общих каталогов и помещайте jar-файлы в каждую WAR-файл приложения.

Эй, спасибо за ответ. Причина этого не в том, что я хочу использовать разные версии библиотеки. У меня есть три военных приложения, все они используют одни и те же библиотеки activeMQ, поэтому я хочу избежать раздувания, то есть загрузки их в память три раза тремя разными загрузчиками. Вот почему я пытаюсь поместить их в общий загрузчик классов.

Mathias 08.05.2024 17:17

Где-то должны быть разные версии Джексона, вызываемые activemq.

aled 08.05.2024 17:32

вы были правы, внутри фактического jar-файла activeMQ были классы Джексона :)

Mathias 24.05.2024 12:16

Другие вопросы по теме