Ответ 1
Во-первых, существует несколько разных понятий типа. Существуют типы времени компиляции, которые включают в себя дженерики. Однако после компиляции генераторы не существуют.
Существует верифицированный статический тип переменной, который может быть int, float, long, double, returnaddress или ссылкой на объект. Ссылки на объекты дополнительно вводятся с верхней границей, так что все ссылки являются подтипами java/lang/String
, например. Поля могут дополнительно иметь один из коротких типов: байт, короткий, char или логический. Они обрабатываются одинаково с ints для целей выполнения, но имеют различное хранилище.
Наконец, существует тип среды выполнения, который совпадает с проверенным статическим типом, но в случае ссылок на объекты представляет собой фактический тип ссылки на экземпляр. Обратите внимание, что из-за верификации верификатора есть некоторые случаи, когда тип выполнения не может быть подтипом проверяемого типа. Например, переменная объявленного типа Comparable
может фактически содержать любой объект в Hotspot, потому что VM не проверяет интерфейсы во время проверки.
Информация о времени компиляции не сохраняется, за исключением дополнительных атрибутов для отражения и отладки. Это потому, что нет оснований для его сохранения.
Локальные переменные не имеют информации о явном типе (кроме нового атрибута StackMapTable, но это техничность). Вместо этого, когда класс загружается, верификатор байт-кода вводит тип для каждого значения, запуская статический анализ потока данных. Цель этого заключается не в том, чтобы ловить ошибки, такие как проверка типа времени компиляции, потому что предполагается, что байт-код уже прошел такую проверку во время компиляции.
Вместо этого целью проверки является обеспечение того, чтобы инструкции не были опасны для самой виртуальной машины. Например, он должен убедиться, что вы не берете целое число и не связываете его как ссылку на объект, поскольку это может привести к произвольному доступу к памяти и взлому виртуальной машины.
Таким образом, хотя значения байт-кода не имеют явной информации о типе, они имеют неявный тип, который является результатом вывода статического типа. Детали этого зависят от внутренних деталей реализации каждой виртуальной машины, хотя они должны следовать стандарту JVM. Но вам придется только беспокоиться об этом в рукописном байт-коде.
Поля имеют явный тип, так как виртуальная машина должна знать, какой тип данных хранится в ней. Параметры метода и типы возвращаемых данных кодируются в так называемом дескрипторе метода, который также используется при проверке типов. Их невозможно вывести автоматически, потому что эти значения могут исходить или уходить куда угодно, в то время как проверка типов выполняется для каждого класса.
P.S. Я пропустил несколько мелких деталей, когда говорил о типах проверки. Типы объектов дополнительно отслеживают, были ли они инициализированы или нет, и какая команда создала их, если они не инициализированы. Типы адресов отслеживают цель созданного ими jsr.