- PVSM.RU - https://www.pvsm.ru -
Многие знают, что в каждом .class-файле есть замечательная структура данных, которая называется пулом констант. Но далеко не каждый Java-разработчик, глядя на исходник, сможет даже примерно оценить, сколько констант будет создано в пуле.
Возьмём, к примеру, такой код:
System.out.println("Hello World!");
Он транслируется в три инструкции байткода: getstatic (для загрузки статического поля System.out), ldc (для загрузки константной строки «Hello World!») и invokevirtual (для выполнения виртуальной функции println). Попробуйте прикинуть, сколько констант нужно для того, чтобы этот код работал.
Оказывается, эта строка использует 14 констант, которые схематично можно изобразить таким образом:
Как мы видим, большинство констант являются ссылками на другие константы. У каждой константы есть тип, значение и номер, по которому на неё можно сослаться. Вот базовые типы, которые ни на что не ссылаются:
А вот некоторые из ссылочных типов:
Для обращения к полю вам нужно не только его имя, но и полное имя класса, где поле объявлено, а также тип поля. Для обращения к методу вам нужен класс, имя и сигнатура метода. К счастью, вся сигнатура кодируется в одну строку вне зависимости от количества параметров метода: примитивные типы кодируются одной буквой (например, D = double), объекты — буквой L, за которой следует полное имя класса и точка с запятой, а один уровень массива добавляет квадратную скобку. В скобочках идут типы аргументов, а за ними — возвращаемый тип (V — это void). Например, сигнатура (IDLjava/lang/Thread;)Ljava/lang/Object;
будет у такого метода:
Object m(int i, double d, Thread t) {...}
От того, что для ссылки на метод требуется его точная сигнатура, разработчики иногда напарываются на NoSuchMethodError. Скажем, вы поменяли возвращаемый тип метода на более конкретный. Тогда вызовы этого метода из других классов остаются прежними, и компилятор не будет пересобирать эти классы, потому что исходные файлы не изменились. Однако при попытке вызвать этот метод во время выполнения, Java-машина будет искать старую сигнатуру.
Если вы автоматически генерируете Java-код, помните, что максимальный номер константы в пуле не превышает 65535, после этого будет ошибка компиляции. Этого не такое большое число, учитывая огромное количество ссылок и то, что long и double занимают по две позиции. Знание устройства пула поможет вам контролировать его заполнение при генерации кода.
Подробнее с устройством пула констант можно ознакомиться в $4.4 [1] спецификации виртуальной машины Java.
Автор: lany
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/news/59730
Ссылки в тексте:
[1] $4.4: http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4
[2] Источник: http://habrahabr.ru/post/222519/
Нажмите здесь для печати.