Здесь есть два момента. Во-первых, есть static
методы, которые вызываются без ссылки this
. Во-вторых, фактический класс экземпляра объекта не обязательно является декларирующим классом метода, код которого мы фактически выполняем. Назначение ссылки на постоянный пул - разрешить разрешение символьных ссылок и загрузку констант, на которые ссылается код. В обоих случаях нам нужен постоянный пул класса, содержащего исполняемый в данный момент код, даже если метод может быть унаследован фактическим классом ссылки this
(в случае метода private
, вызванного другим унаследованным методом, у нас есть метод, вызываемый с this
экземпляром класса, который формально даже не наследует метод).
Может даже случиться, что текущий исполняемый код содержится в интерфейсе, поэтому у нас никогда не бывает его экземпляров, но все равно есть файл класса с постоянным пулом, который должен быть доступен при выполнении кода. Это относится не только к Java 8 и новее, которые допускают методы static
и default
в интерфейсах; более ранние версии также могут нуждаться в выполнении метода <clinit>
интерфейса для инициализации его полей static
.
Кстати, даже если метод экземпляра вызывается со ссылкой на объект, связанный с this
в его первой локальной переменной, для инструкций байт-кода не требуется сохранять его там. Если в этом нет необходимости, он может быть перезаписан произвольным значением, повторно используя слот переменной для других целей. Это не исключает того, что последующим инструкциям необходим постоянный пул, который, как уже было сказано, не обязательно должен принадлежать фактическому классу this
.
Конечно, ссылка на пул в любом случае является логической конструкцией. Реализации могут преобразовывать код для использования общего пула или вообще не требовать его, когда все ссылки уже разрешены и т. Д. После встраивания у кода может даже не быть выделенного стекового фрейма.