Java编译的.class文件中pop2双栈值操作的场景及示例代码问询
pop2 opcode appear in Java .class files, and what are examples of it operating on two stack values? Great questions—let's break this down clearly, since you're working on a decompiler, understanding these edge cases is key.
1. When does pop2 show up in compiled bytecode?
The pop2 opcode serves two distinct purposes in JVM bytecode, so you'll encounter it in two main scenarios:
- Discarding a single category 2 type: Values of type
longordoubletake up two slots on the operand stack, sopop2is used to remove them (since a regularpoponly handles one slot). - Discarding two category 1 types: When there are two separate category 1 values (like
int,float, object references,boolean, etc.) sitting on the operand stack that need to be removed together. The compiler will often usepop2here instead of two consecutivepopopcodes for efficiency.
2. Scenarios and example code for pop2 operating on two stack values
The most common scenario for this is when your Java code has unused expressions that push two separate category 1 values to the stack, and the compiler can't optimize those expressions away. Since the values are unconsumed, the JVM needs to clean them up, and pop2 is the efficient way to do it.
Here's a concrete example that will generate pop2 for two category 1 values when compiled:
public class Pop2TwoValuesExample { public static void main(String[] args) { int x = 5; int y = 10; // The compiler can't optimize away this block because args != null isn't a compile-time constant if (args != null) { // These two expressions push x and y to the operand stack but don't use them x; y; } } }
Why this generates pop2
Compile this code with javac Pop2TwoValuesExample.java, then inspect the bytecode with javap -c Pop2TwoValuesExample. You'll see this in the main method's bytecode:
public static void main(java.lang.String[]); Code: 0: iconst_5 1: istore_1 2: bipush 10 4: istore_2 5: aload_0 6: ifnull 15 9: iload_1 // Push the int value of x (category 1) to the stack 10: iload_2 // Push the int value of y (category 1) to the stack 11: pop2 // Pop both values in one operation 12: goto 15 15: return
The iload_1 and iload_2 instructions push two separate int values to the stack. Since those values aren't used anywhere, the compiler inserts a pop2 to clean them both up at once, rather than using two pop opcodes.
This is a perfect example of pop2 operating on two category 1 stack values, which is exactly what you're looking for in your decompiler work.
内容的提问来源于stack exchange,提问作者Jiann Lan

