Ответ 1
Эти инструкции печатаются, чтобы гарантировать, что программа является типичной. При загрузке класса виртуальная машина выполняет проверку на байт-кодах, чтобы гарантировать, что, например, float не передается в качестве аргумента методу, ожидающему целое число. Эта статическая проверка требует, чтобы верификатор мог определять типы и количество значений в стеке для любого заданного пути выполнения. Инструкции по загрузке и хранению требуют тега типа, поскольку локальные переменные в кадрах стека не печатаются (т.е. Вы можете использовать локальную переменную и позже 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
.