Эти инструкции напечатаны, чтобы гарантировать безопасность программы. При загрузке класса виртуальная машина выполняет проверку байтовых кодов, чтобы убедиться, что, например, число с плавающей запятой не передается в качестве аргумента методу, ожидающему целое число. Эта статическая проверка требует, чтобы верификатор мог определить типы и количество значений в стеке для любого заданного пути выполнения. Инструкции загрузки и сохранения нуждаются в теге типа, поскольку локальные переменные в кадрах стека не набираются (то есть вы можете восстановить локальную переменную, а затем fstore в той же позиции). Теги типа в инструкциях позволяют верификатору знать, какой тип значения хранится в каждой локальной переменной.
Верификатор просматривает каждый код операции в методе и отслеживает, какие типы будут в стеке и локальных переменных после выполнения каждого из них. Вы правы, что это еще одна форма проверки типов, которая дублирует некоторые проверки, выполняемые компилятором java. Этап проверки предотвращает загрузку любого кода, который может привести к тому, что виртуальная машина выполнит недопустимую инструкцию, и обеспечит свойства безопасности платформы Java без больших потерь времени выполнения проверки типов перед каждой операцией. Проверка типа во время выполнения для каждого кода операции будет снижать производительность при каждом выполнении метода, но статическая проверка выполняется только один раз при загрузке класса.
Дело 1:
Instruction Verification Stack Types Local Variable Types
----------------------- --------------- ---------------------- -----------------------
<method entry> OK [] 1: none
iconst_1 OK [int] 1: none
istore_1 OK [] 1: int
return OK [] 1: int
Дело 2:
Instruction Verification Stack Types Local Variable Types
----------------------- --------------- ---------------------- -----------------------
<method entry> OK [] 1: none
iconst_1 OK [int] 1: none
fstore_1 Error: Expecting to find float on stack
Ошибка возникает из-за того, что верификатор знает, что fstore_1 ожидает float в стеке, но результат выполнения предыдущих инструкций оставляет int в стеке.
Эта проверка выполняется без выполнения кодов операций, скорее, она выполняется путем просмотра типов инструкции, так же, как компилятор java выдает ошибку, когда вы пишете (Integer)"abcd"
. Компилятору не нужно запускать программу, чтобы знать, что "abcd"
является строкой и не может быть приведен к Integer
.