WAS 6.1 java.lang.VerifyError: нарушение загрузки класса нарушено
В Linux используется среда WAS 6.1, развертывание webapp, использующего
классы из xercesImpl.jar.
Из-за ограничений политики компании приложение должно быть развернуто с помощью
Параметры:
Class Loader Order
Classes loaded with parent class loader first
-> Classes loaded with application class loader first
WAR class loader policy
Class loader for each WAR file in application
-> Single class loader for application
Файл WAR содержит копию xercesImpl.jar, то же самое, что
был в classpath, когда приложение было скомпилировано.
При запуске webapp, когда Spring пытается разобрать свои конфиги, он
броски:
java.lang.VerifyError: class loading constraint violated
(class: org/apache/xerces/jaxp/DocumentBuilderImpl
method: parse(Lorg/xml/sax/InputSource;)Lorg/w3c/dom/Document;)
АНАЛИЗ SO FAR
Похоже, что WAS обеспечивает реализацию
org.apache.xerces.jaxp.DocumentBuilderImpl, потому что мы можем удалить
xercesImpl.jar из WAR файла и по-прежнему получают ту же ошибку (не
ClassNotFoundException). Таким образом, WAS, похоже, решает ссылки
используя свою собственную копию, которая несовместима со ссылками в наших
скомпилированные файлы классов. Тем не менее, единственный другой экземпляр "xercesImpl.jar"
Я могу найти (кроме копии, развернутой с нашим приложением), находится в каталоге
deploytool
, который, кажется, находится за пределами сервера приложений.
Я просмотрел все банки в WAS (все 1300 из них) с помощью
for i in `find . -name \*.jar`; do jar tvf $i|grep -qi xerces && echo $i ; done
и обнаружил, что ./java/jre/lib/xml.jar
содержит все классы в org.apache.xerces.*
,
так что это, вероятно, где classloader разрешает ссылку.
ЗДЕСЬ ЧАСТЬ ВЕРЫ:
Если мы сначала перейдем к "загрузчику родительского класса", мы не увидим исключение.
Это противоречит ожидаемому поведению. Мы ожидаем, что с
"application classloader first", он будет использовать xercesImpl.jar, чтобы мы
и использовать версию WAS, только если мы установили "родительский загрузчик классов"
сначала ". Это, кажется, назад от того, что мы видим на самом деле.
ВОПРОС:
Как параметр делегирования загрузчика классов, взаимодействующий с вышеуказанной информацией, приводит к наблюдаемому поведению?
Ответы
Ответ 1
Ваша WAR также включает классы org.xml.sax или org.w3c.dom, а затем вы ссылаетесь на класс, который находится вне вашего приложения, который также ссылается на эти классы. Это устанавливает сценарий, когда ваш загрузчик класса приложения имеет видимость для двух экземпляров одного и того же класса, что является ошибкой связи.
Например, если ваше приложение использует javax.xml.bind.Unmarshaller.unmarshal(InputSource), то Unmarshaller будет загружен из JDK, а класс Unmarshaller будет иметь видимость для InputSource JDK. Когда ваше приложение создает свой InputSource, оно будет загружать класс из WAR (потому что политика "первым приложением" ), а затем ваше приложение попытается передать экземпляр WAR InputSource на Unmarshaller JDK, который может принимать только экземпляр источник входных данных JDK.
Существует два решения:
- Удалите все API-банки из вашего приложения и используйте те из JDK. Например, удалите банку, содержащую org.xml.sax или org.w3c.dom.
- Включите все библиотеки вашей WAR, которые ссылаются на классы, которые вы хотите ссылаться. Например, включите копию вашей библиотеки JAXB в WAR.
По моему опыту, ошибки сцепления довольно сложно отследить, потому что JVM дают паршивую информацию о том, что вызывает добавление связей. Я обычно включаю трассировку загрузчика классов, воспроизвожу проблему, а затем иду назад, пока не найду класс, загруженный извне приложения, которое "звучит", оно может ссылаться на класс, который, как известно, существует внутри приложения.
Ответ 2
Наша проблема заключалась в развертывании на WAS 8.5.
В нашем веб-приложении у нас есть клиент веб-службы, созданный cxf. Нет проблем.
Когда мы добавили в tika-parser для обнаружения типа mime, мы получили эту проблему.
Мы исключили три зависимости:
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers</artifactId>
<version>${apache.tika.version}</version>
<exclusions>
<exclusion>
<artifactId>geronimo-stax-api_1.0_spec</artifactId>
<groupId>org.apache.geronimo.specs</groupId>
</exclusion>
<exclusion>
<artifactId>xercesImpl</artifactId>
<groupId>xerces</groupId>
</exclusion>
<exclusion>
<artifactId>xmlbeans</artifactId>
<groupId>org.apache.xmlbeans</groupId>
</exclusion>
</exclusions>
</dependency>
Как только они были исключены, наше приложение успешно запущено.
Ответ 3
Отключить проверку байтового кода
java.lang.VerifyError - Неверное исключение времени выполнения
как только файл класса загружается в JVM Websphere, тогда валидация кода байта является следующим процессом. Если проверка байтового кода, если наш класс нарушает ограничения JVM, появляется эта ошибка.
отключить проверку байт-кода. Перейдите в
admin console ->
server1 ->
java и управление процессами ->process definition->
Аргументы JVM
И в аргументах JVM передайте следующую строку
-Xverify:none
и в рабочей области откройте файл ApplicationDeploymentDescriptor xml, перейдите на вкладку развертывания, выберите PARENT_LAST для войны, а также для первого варианта. это останавливает ошибки проверки xml.
Ответ 4
Если мы перейдем к "загрузчику родительского класса сначала" мы не видим исключения. Это противоречит ожидаемому поведение.
Да, это правильно, это единственный способ увидеть такое поведение. Я могу посоветовать вам взглянуть на "Вы действительно получаете классных погрузчиков?" говорить, так как нет ни одного или короткого ответа на ваш вопрос.
http://www.slideshare.net/guestd56374/do-you-really-get-class-loaders
http://www.parleys.com/#sl=2&st=5&id=1585