В моем проекте инструментирования байт-кода я часто натыкаюсь на VerifyErrors. Однако java Verifier по умолчанию дает мало информации о том, какая инструкция привела к ошибке (он дает только метод и небольшое сообщение). Есть ли какой-нибудь автономный верификатор байт-кода, который предоставляет немного более продвинутую помощь в обнаружении ошибки, по крайней мере, точное местоположение инструкции? Спасибо.
Автономный верификатор байт-кода
Ответы (3)
Как и в любом проекте, использующем байт-код JVM, я бы сначала проверил, есть ли в BCEL что-нибудь, что может быть полезным для вас. Кроме того, возможно, FindBugs может помочь, хотя я не уверен, предполагает ли он проверяемый байт-код для начала или нет. .
ASM CheckClassAdaptor.verify() дает отличную обратную связь: http://asm.ow2.org/
Я также искал что-то, что сообщало бы о потенциальных ошибках проверки, но особенно IncompatibleClassChangeError
s. Я написал небольшой тестовый проект с одним классом API и другим клиентским классом, вызывающим методы API, а также с основным классом для запуска верификатора; затем изменили API, перекомпилировав его, но не клиент, и проверили, что можно поймать. Использовал -target 7
, хотя пока никаких специальных функций JDK 7 нет.
Во-первых, и это наиболее очевидно, Class.forName
может найти определенные ошибки в сигнатуре клиентского класса, но, похоже, он не проверяет тела методов на наличие вызовов несуществующих методов API и т.п., даже если вы вызываете getDeclaredMethods
; об ошибках сообщает виртуальная машина только тогда, когда проблемная строка кода действительно выполняется.
JustIce в BCEL 5.2 кажется самым простым;
org.apache.bcel.verifier.Verifier.main(new String[] {clazz});
делает работу:
Pass 3a, method number 1 ['public void m()']:
VERIFIED_REJECTED
Instruction invokestatic[184](3) 4 constraint violated:
Referenced method 'x' with expected signature '()V' not found in class 'API'.
....
Я пробовал ASM 4.0, но
org.objectweb.asm.util.CheckClassAdapter.main(new String[] {clazz});
не работает; возможно, он проверяет формат методов, но не компоновку. Встраивание main
и передача checkDataFlow=true
не помогают.
При поиске я также нашел https://kenai.com/hg/maxine~maxine/file/8429d3ebc036/com.oracle.max.vm/test/test/com/sun/max/vm/verifier/CommandLineVerifier.java, но я не смог найти способ заставить это работать; сопутствующий модульный тест выдает ClassNotFoundException
при запуске.