2015-10-17 1 views
1

JVM имеет две команды: bipush (. Значение операнда должно быть между Byte.MIN_VALUE и Byte.MAX_VALUE) и sipush (значение операнда должно быть между Short.MIN_VALUE и Short.MAX_VALUE). Соответственно, MethodVisitor в ASM обеспечивают API, чтобы управлять этими двумя инструкциями:Как загружать различные примитивные ДАННЫЕ в стек операндов

 public void visitIntInsn(int opcode, int operand) 

Поэтому, как посетить другие не байт (короткие) примитивы в ASM? Например, примитивы long, double, int, boolean и float данные? Странно, что эти данные обернуты как Long, Double, Integer.

ответ

5

Булевы только на уровне JVM. Нажмите 0 для false и 1 для true. Для этого вам не нужна бипуша, вы можете просто использовать iconst_0 и iconst_1.

Байт, шорты, символы и т. Д. - все это также просто на уровне JVM. В байткоде нет понятия коротких примитивных типов, только функции усечения (i2c и co).

Если вы хотите нажать значение 111, вы должны использовать bipush 111. Если вы хотите нажать 1111, вы должны использовать sipush 1111. Если вы хотите нажать 111111, вы должны использовать ldc 111111. Они все просто на уровне байт-кода.

Для поплавков, парных и длинномерных изделий в большинстве случаев вы должны использовать семейство инструкций ldc*. В частном случае 0 или 1 констант, вы можете использовать вместо lconst_0, dconst_1 и т.д.

Вы можете создать ldc инструкции ASM с помощью метко названный MethodVisitor.visitLdcInsn.

Удостоверьтесь, что ldc требует пространства в постоянном пуле, который ограничен 65534 слотами. Тем не менее, он достаточно велик, что вы никогда не столкнетесь с практическими обстоятельствами. Если вы действительно этого хотите, вы можете нажать более крупные примитивные значения без использования пула констант, используя математику для построения значений.

Например, int 111111 может быть образован на iconst_3 bipush 15 ishl sipush 12807 iadd. Enjarify имеет код для этого для каждого примитивного типа, даже удваивается, хотя обычно они принимают множество инструкций для представления по очевидным причинам. Однако, если вы используете ASM, вы, вероятно, не делаете ничего необычного и достаточно сложного, чтобы требовать такого подхода.

+1

Обратите внимание, что в ASM 'push (0)' или 'push (false)' автоматически генерирует инструкцию 'iconst_0', а не' bipush 0', поэтому вы работаете с чуть более высоким уровнем абстракции. –

+0

Я бы не использовал эту сложную последовательность команд для '111111', тем более что она не короче пространства, необходимого в пуле констант. Тем не менее, использование чего-то вроде 'iconst_5, i2l' для нажатия' long' constant '5L' является разумным, imho. – Holger

+0

@ Хольгер, это специально для случая, когда вы исчерпали пространство в постоянном пуле. Как я уже сказал, это не нормальное явление. – Antimony