Почему изменение порядка каталогов файлов JAR в WEB-INF / lib вызывает NoClassDefFoundError в Tomcat 8? - PullRequest
0 голосов
/ 11 мая 2018

У нас есть веб-приложение, которое мы запускаем в Tomcat 8, и недавно мы заметили, что артефакты (файлы .war), созданные некоторыми разработчиками в нашей команде, выдают NoClassDefFoundError, тогда как тот же код, созданный другими функциямикак и ожидалось.

С logs/localhost.2018-05-11.log:

org.jboss.resteasy.spi.UnhandledException: java.lang.NoClassDefFoundError: Could not initialize class org.geotools.referencing.datum.DefaultEllipsoid
    ...
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.geotools.referencing.datum.DefaultEllipsoid
    at org.geotools.referencing.GeodeticCalculator.<init>(GeodeticCalculator.java:277)
    ...

Иногда, но не всегда, сопровождается (предшествует):

org.jboss.resteasy.spi.UnhandledException: java.lang.IncompatibleClassChangeError: Implementing class
    ...

Исследование войныфайлы, содержимое рабочих и поврежденных артефактов выглядит идентично, за одним заметным исключением «упорядочение каталогов» файлов jar в WEB-INF/lib отличается.

Выполнение следующей процедуры над разобранным файлом warи перезапуск Tomcat, по-видимому, устраняет исключение:

$ # jars in "bad" order
$ ls -U WEB-INF/lib
x.jar
b.jar
y.jar
a.jar
c.jar
z.jar
$ cp -p WEB-INF/lib/* /tmp/lib/
$ rm -r WEB-INF/lib
$ mv /tmp/lib WEB-INF/lib
$ # jars in "good" order (appears to be alphabetical after a 'cp' on my system)
$ ls -U WEB-INF/lib
a.jar
b.jar
c.jar
x.jar
y.jar
z.jar

«Хорошие» войны не содержат банок в алфавитном порядке, но, похоже, существует ряд «хороших» порядков, а не «плохих»"orders.

Сначала я думал, что у нас может быть несколько версий класса DefaultEllipsoid в разных банках, что приводит к состоянию гонки между правильной версией и другой версией, но tпохоже, это не тот случай.

Я включил подробную отладку загрузчика классов в tomcat, и в обоих случаях logs/catalina.out показывает, что этот класс загружается из правильного jar:

[Loaded org.geotools.referencing.datum.DefaultEllipsoid from file: /opt/tomcat/temp/1-webapp/WEB-INF/lib/gt-referencing-11.4.jar]

Есть идеи о том, что здесь может происходить?

Подробности:

  • CentOS 7
  • Apache Tomcat / 8.0.43
  • Java 1.8.0_144
  • Apache Maven 3.3.9

Ответы [ 4 ]

0 голосов
/ 21 мая 2018

Строка:

Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.geotools.referencing.datum.DefaultEllipsoid

означает, что класс DefaultEllipsoid найден, но, чтобы быть действительным, есть некоторый другой класс , который необходимо загрузить, но это не удалось.Другой класс недействителен.

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

Кроме того, из tomcat8, аппликативногоjar-файлы в WEB-INF/lib NOT загружаются в алфавитном порядке.Я думаю, что был документ с этим на сайте tomcat, но сейчас я его больше не нахожу, но нашел ошибку регрессии (не исправлю) в ошибка tomcat bugzilla 57129

Этот материал загрузчика классов означает, что если вы измените некоторые вещи в WEB-INF/lib и перезапустите Tomcat, тогда будет случайная загрузка классов, которая заставит ваше приложение загружаться тем или иным образом, если есть дублирующая версия jar.

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

0 голосов
/ 17 мая 2018

Порядок банок будет иметь значение.в основном загрузчик классов загружает их таким образом.Поэтому, когда существует несколько версий одного и того же класса, вы можете получить этот NoClassdefFoundError или java.lang.IncompatibleClassChangeError: он может видеть ваши классы, но не знает, какой использовать, или классы модифицированы и размещены в нескольких банках.Проверьте ваши банки, если есть какие-либо дублирующие классы, тогда вы можете устранить основную причину.

0 голосов
/ 17 мая 2018

Было дано несколько интересных ответов на похожий вопрос Что вызывает IncompatibleClassChangeError , предполагая, что вы и другие разработчики не используете одни и те же файлы JAR во время компиляции.Сравните (по крайней мере, размер файла, но контрольная сумма была бы лучше) каждый jar-файл, использованный для компиляции, и снова те, которые использовались во время выполнения, конечно же, те, которые вы используете сами, и файлы, используемые другими разработчиками.

0 голосов
/ 16 мая 2018

По запросу K. Sopheak и amod (модераторы) я обновляю.

Существует одна причина этого исключения, связанная с временным каталогом Tomcat.

Временные файлы из предыдущего развертывания может вызвать это.Проверьте workDir (значение по умолчанию: $TOMCAT_BASE/work) и, когда Tomcat остановлен, очистите его, удалив все.

...