Минимальный пример, который генерирует ошибку
Одной простой возможностью является использование Jasmin или ручное редактирование байт-кода с помощью редактора двоичных файлов.
Позволяет создать метод void
без инструкции return
(сгенерированной инструкцией return;
в Java), которую JVMS считает недопустимой.
В Жасмин мы могли бы написать:
.class public Main
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
aload_0 ; Just so that we won't get another verify error for empty code.
.end method
Затем мы делаем javac Main.j
и javap -v Main
говорит, что мы скомпилировали:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
так что на самом деле инструкции возврата нет.
Теперь, если мы попытаемся запустить java Main
, мы получим:
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.VerifyError: (class: NoReturn, method: main signature: ([Ljava/lang/String;)V) Falling off the end of the code
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Эта ошибка никогда не может происходить в Java в обычном режиме, поскольку компилятор Java добавляет нам неявные return
к void
методы. Вот почему нам не нужно добавлять return
к нашим main
методам. Вы можете проверить это с помощью javap
.
JVMs
VerifyError происходит, когда вы пытаетесь запустить определенные типы недопустимых файлов классов, как указано в JVMS 7, глава 4.5
JVMS говорит, что когда Java загружает файл, она должна выполнить серию проверок, чтобы убедиться, что файл класса в порядке, прежде чем запускать его.
Такие ошибки не могут быть сгенерированы в одном цикле компиляции и выполнения кода Java, потому что JVMS 7 4.10 сообщает :
Хотя компилятор для языка программирования Java должен создавать только файлы классов, которые удовлетворяют всем статическим и структурным ограничениям [...
]
Итак, чтобы увидеть пример минимального сбоя, нам нужно сгенерировать исходный код без javac
.