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