JEP 136: Enhanced Verification Errors
Расширенные сообщения об ошибках верификации
| Автор | Keith McGuigan |
| Ответственный | Keith Mcguigan |
| Тип | Feature |
| Область | Implementation |
| Статус | Closed / Delivered |
| Выпуск | 8 |
| Компонент | hotspot / runtime |
| Обсуждение | hotspot dash runtime dash dev at openjdk dot java dot net |
| Трудоёмкость | S |
| Длительность | S |
| Одобрен | Mikael Vidstedt |
| Создан | 2011/11/30 20:00 |
| Обновлён | 2017/06/14 19:40 |
| Задача | 8046126 |
Аннотация
Добавить в ошибки верификации байт-кода дополнительную контекстную информацию, чтобы упростить диагностику дефектов байт-кода или stackmap в реальной эксплуатации.
Цели
Байт-код проверяется верификатором байт-кода JVM. Компилятор javac из JDK, как правило, генерирует байт-код, в высокой степени соответствующий спецификации. Однако существуют и другие инструменты и пакеты, которые изменяют байт-код по разным причинам, в том числе для инструментирования и отладки. Иногда постобработка байт-кода приводит к VerifyError. Сейчас сообщение, связанное с этой ошибкой, довольно лаконично и неконкретно. Цель этой возможности — расширить информацию, доступную при возникновении VerifyError в современных class-файлах, чтобы разработчик мог быстрее устранить проблему.
Что не является целью
Хотя об ошибках можно сообщать дополнительные данные, целью не является предоставление «всех возможных» данных об ошибке, особенно в случаях, когда дополнительные данные можно получить другими способами. Например, хотя байт-код, в котором возникла проблема, может быть включён в сообщение об ошибке, он может не дизассемблироваться в удобочитаемую форму. Кроме того, состояние системы, например загруженные классы и связи между ними, не предоставляется, поскольку эта информация доступна с помощью других механизмов.
Эти дополнительные данные будут доступны и будут выводиться только для ошибок, которые генерирует верификатор с проверкой типов. Class-файлы с версией ниже 50 проверяются верификатором с выводом типов. Ошибки, генерируемые верификатором с выводом типов, не изменятся.
Формат сообщения об ошибке и его данных не является официальным и не специфицирован полностью, и может измениться в любом выпуске.
Критерии успеха
Проект будет считаться успешным, если дополнительные данные будут использованы хотя бы одним инженером для диагностики реальной ситуации с ошибкой верификации. Учитывая непредсказуемость проблемы и продолжающееся нежелание инженеров разрешить вживлять себе в мозг чипы слежения, никакой полезной метрики, которую можно было бы применить в этом случае, по сути нет. Приходится полагаться на здравый смысл и опыт, определяя, что скорее всего окажется полезным, а это исторически общеизвестно трудно поддаётся количественной оценке.
Мотивация
Ошибки верификации трудно расшифровать. Нынешние сообщения, прикрепляемые к сообщениям VerifyError, малопонятны и почти не помогают точно определить, где и почему байт-код или stackmap содержит изъян.
Описание
Этот проект состоит из двух частей. Первая — открытие ранее внутреннего флага, который трассирует проект верификации, вторая — дополнение сообщений, содержащихся в VerifyError, дополнительной контекстной информацией.
Флаг, включающий трассировку верификации, ранее был внутренним глобальным флагом, и для его включения требовались изменение исходного кода и (в отладочном режиме) перекомпиляция JVM. Этот проект превращает данный флаг в диагностический флаг «VerboseVerification». Таким образом, трассировку верификации можно включить (даже в режиме product) с помощью флагов командной строки: «-XX:+UnlockDiagnosticVMOptions -XX:+VerboseVerification»
При запуске с включённым флагом JVM будет выводить трассировочную информацию в stdout. Эта трассировочная информация подробно показывает, какие методы проверяются, какой механизм используется для верификации, таблицу stackmap метода. а в отладочном режиме — bci, опкод и текущее состояние фрейма для каждой инструкции.
Кроме того, традиционное сообщение об ошибке, включаемое в выбрасываемый экземпляр VerifyError, дополняется следующей подробной информацией: точное место, где обнаружена ошибка (имя класса и метода плюс смещение в байт-коде); более подробное уведомление об ошибке с описанием происхождения всех упоминаемых типов (если применимо); текущее состояние анализируемого фрейма (если применимо); шестнадцатеричный дамп байт-кода; текстовое представление таблицы обработчиков исключений; текстовое представление таблицы stackmap.
Дополнительные сведения об ошибке разбиты на разделы и представлены в многострочном формате в сообщении исключения. Исходное сообщение об ошибке также не изменяется и находится в начале сообщения исключения.
Альтернативы
Одна из альтернатив — не дополнять сообщения подробностями об ошибке, если не указан флаг командной строки. Такой вариант всё ещё возможен, но поскольку VerifyError возникают редко, предполагается, что наличие дополнительных подробностей по умолчанию не вызовет никаких проблем.
Тестирование
Для проверки этой возможности можно использовать существующие наборы тестов для верификатора байт-кода. Однако некоторые тесты, возможно, придётся доработать, чтобы они ожидали дополнительную диагностическую информацию, которую предоставляет эта возможность.
Всестороннее тестирование требует написания ряда тестов (каждый из которых представляет собой специально подготовленный class-файл), вызывающих VerifyError в каждом возможном месте кода, а также создания разнообразных тестов, проверяющих различные источники происхождения типов (стек/локальные переменные/пул констант).
Риски и допущения
Риск очень низкий. Мы предполагаем, что никто не зависит от нынешнего содержимого сообщения исключения VerifyError, и поэтому его можно безопасно дополнить без проблем с совместимостью. Если это предположение окажется неверным, возможно, нам стоит изучить указанную альтернативу.
Зависимости
Зависимостей нет
Влияние
Мы не ожидаем влияния на другие части платформы.