java.lang.LinkageError на jBoss при запуске приложения с классом пользовательского макета log4j - PullRequest
1 голос
/ 19 марта 2010

Я пытаюсь настроить собственный класс макета для Log4J, как описано в моем предыдущем посте . Класс использует java.util.regex.Matcher для идентификации номеров потенциальных кредитных карт в сообщениях журнала. Он отлично работает в модульных тестах, а также в минимальном веб-приложении, содержащем один сервлет. Однако, когда я пытаюсь развернуть его с нашим приложением в JBoss, я получаю следующую ошибку:

--- MBEANS THAT ARE THE ROOT CAUSE OF THE PROBLEM ---
ObjectName: jboss.web.deployment:war=MyWebApp-2010_02-SNAPSHOT.war,id=476602902
  State: FAILED
  Reason: java.lang.LinkageError: java/util/regex/Matcher

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

Технические подробности: мы используем JBoss 4.2, Java 5, Log4J 1.2.12. Мы разворачиваем наше приложение в .ear, который содержит (помимо прочего) вышеупомянутый .war-файл и пользовательский класс макета в отдельном jar-файле (назовем его Commons). Мы переопределяем настройки по умолчанию в jboss-log4j.xml на наш собственный log4j.properties, расположенный в другой папке, которая добавляется в путь к классам при запуске и предоставляется через Sapient's Carbon framework .

Обновление до ответа @ skaffman:

Причиной, по которой у нас есть отдельный файл log4j.properties, является схема, распространяемая Sapient Carbon. Это в основном отделяет файлы конфигурации и данных от среды сервера приложений, так что они доступны через функцию поиска Carbon и могут храниться в каталоге, внешнем по отношению к серверу приложений. Мы унаследовали эту настройку и ненавидим ее, потому что она вызывает у нас много проблем с развертыванием, проблемами с classpath и т. Д., Поскольку она не соответствует соглашениям JEE. Мы стремимся избавиться от этого в долгосрочной перспективе, но это займет время: - (

Несмотря на то, что отдельный файл log4j.properties не рекомендуется, он, безусловно, работает. Он работал в нашем приложении в течение многих лет, и я мог бы также заставить его работать с минималистским веб-приложением, содержащим один сервлет (без использования Sapient Carbon). Если log4j.properties помещен в classpath, Log4J правильно читает его при запуске веб-приложения и соответствующим образом перенастраивает ведение журнала.

Обновление # 2: Интересный вывод заключается в том, что Matcher даже не используется в MyWebApp, только в модуле Commons (и другом модуле, в отдельном фляге). В Commons он ранее использовался в классе StringHelper, который косвенно используется MyWebApp через другие модули.

Полагаю, это исключает возможность загрузки двух разных версий классов Matcher разными загрузчиками классов. Таким образом, мое единственное оставшееся предположение состоит в том, что Matcher загружается двумя разными загрузчиками классов, когда он используется с фляги и войны, а затем пытается перейти от одного к другому. Это объясняется превосходной статьей Фрэнка Киевета . Однако я полагаю, что такая настройка вызовет «нарушение ограничения загрузчика», а не эту форму ошибки.

Обновление № 3: если я добавлю этого приложения (пример 3.8) в jboss-log4j.xml, ошибка исчезнет, ​​и сервер будет работать отлично : -o Это, очевидно, имеет сделать что-то с загрузкой log4j.jar, потому что эта настройка требует, чтобы jar присутствовал в каталоге lib сервера. Это также работает, если я изменил тип appender на org.jboss.logging.appender.FileAppender и установил уровень журнала на WARN, что привело бы к пустому файлу ucl.log. Это может подойти как временное решение, но я все еще хочу полностью понять, что здесь происходит.

Что означает это сообщение об ошибке и как его исправить?


Эпилог

После долгого ожидания мне наконец удалось исключить Carbon из процесса регистрации и перенести нашу конфигурацию регистрации в server/conf/jboss-log4j.xml. Это потребовало, чтобы я опубликовал наш собственный класс фильтра журналов в отдельном jar-каталоге в каталоге server/lib. После этого загрузка класса снова работает без обходного пути, описанного в обновлении № 3 выше: -)

Ответы [ 2 ]

1 голос
/ 21 марта 2010

Моя первая реакция заключается в том, что в JBoss невозможно переопределить конфигурацию log4j таким образом. JBoss не позволяет log4j находить свою собственную конфигурацию, как обычно, местоположение conf/jboss-log4j.xml указано в conf/jboss-service.xml.

Насколько мне известно, вся конфигурация log4j на данном сервере JBoss должна быть централизована в одном файле, обычно conf/jboss-log4j.xml.

Вы пытались в качестве теста переместить содержимое вашего log4j.properties в существующий файл conf/jboss-log4j.xml? Если это работает нормально, то проблема почти наверняка вызвана вашей попыткой переопределить log4j. Сказав это, я буду удивлен, если jboss / log4j настолько хрупок, но, возможно, в некоторых случаях он отвергает это.

1 голос
/ 19 марта 2010

у вас либо два класса разных подписей, но один и тот же путь в вашей среде, либо вы скомпилировали с другой подписью j.u.r.Matcher. Так как это стандартный Java API, я думаю, вам следует проверить исходные коды и цели компиляции, а также версию JVM для вашей установки JBoss.

Edit:

После того, как это исключено, я уверен, что загрузчик классов (сервер), который управляет приложениями и пытается загрузить приложение, использующее ваш пользовательский макет, не может видеть экземпляр класса пользовательского макета. Итак, у вас есть два варианта:

  1. Разверните пользовательский макет JAR в каталоге lib сервера вместе с log4j.
  2. Разверните log4j вместе с вашим приложением и изолируйте приложение с помощью собственного загрузчика классов (jboss-app.xml):

<jboss-app> <loader-repository> com.myapplication:loader=MyClassLoader <loader-repository-config>java2ParentDelegation=false</loader-repository-config </loader-repository> </jboss-app>

Надеюсь, тогда проблема исчезнет.

...