JVM有两条指令:bipush
(操作数值应介于Byte.MIN_VALUE
和Byte.MAX_VALUE
之间。)和sipush
(操作数值应介于Short.MIN_VALUE
之间Short.MAX_VALUE
)。相应地,ASM中的MethodVisitor
提供API来操作这两个指令:
public void visitIntInsn(int opcode, int operand)
因此,如何访问ASM中的其他非字节(短)基元?例如,原始long
,double
,int
,boolean
和float
数据?看起来很奇怪这些数据包含在Long
,Double
,Integer
。
答案 0 :(得分:5)
布尔值只是JVM级别的整数。将0推送为false,将1推送为true。您不需要使用bipush,只需使用iconst_0
和iconst_1
。
字节,短路,字符和整数也都是JVM级别的内容。字节码中没有短基元类型的概念,只有截断函数(i2c
和co)。
如果要推送int值111,可以使用bipush 111
。如果你想推1111,你会使用sipush 1111
。如果要推送111111,则使用ldc 111111
。它们都只是字节码级别的内容。
对于浮点数,双打数和长数字,在大多数情况下,您必须使用ldc*
系列指令。对于0或1常量的特殊情况,您可以改为使用lconst_0
,dconst_1
等。
您可以使用恰当命名的MethodVisitor.visitLdcInsn在ASM中创建ldc
条指示。
请注意,ldc
需要常量池中的空间,该空间限制为65534个插槽。但是,它足够大,你永远不会在实际情况下用完。如果你真的想要,你可以通过使用数学来构造值,而不使用常量池来推送更大的原始值。
例如,int {11}可以由iconst_3 bipush 15 ishl sipush 12807 iadd
生成。 Enjarify有代码为每个主要类型执行此操作,甚至是双倍,尽管他们通常需要更多指令来表示,原因很明显。但是,如果你正在使用ASM,那么你可能没有做任何不寻常和复杂的事情来要求这种方法。