📄 opcodestack.java
字号:
case IASTORE: case LASTORE: case SASTORE: pop(3); break; case BIPUSH: case SIPUSH: push(new Item("I", (Integer)dbc.getIntConstant())); break; case IADD: case ISUB: case IMUL: case IDIV: case IAND: case IOR: case IXOR: case ISHL: case ISHR: case IREM: case IUSHR: it = pop(); it2 = pop(); pushByIntMath(seen, it2, it); break; case INEG: it = pop(); if (it.getConstant() != null) { push(new Item("I", ( Integer)(-(Integer) it.getConstant()))); } else { push(new Item("I")); } break; case LNEG: it = pop(); if (it.getConstant() != null) { push(new Item("J", ( Long)(-(Long) it.getConstant()))); } else { push(new Item("J")); } break; case DNEG: it = pop(); if (it.getConstant() != null) { push(new Item("D", ( Double)(-(Double) it.getConstant()))); } else { push(new Item("D")); } break; case LADD: case LSUB: case LMUL: case LDIV: case LAND: case LOR: case LXOR: case LSHL: case LSHR: case LREM: case LUSHR: it = pop(); it2 = pop(); pushByLongMath(seen, it2, it); break; case LCMP: handleLcmp(); break; case FCMPG: case FCMPL: handleFcmp(seen); break; case DCMPG: case DCMPL: handleDcmp(seen); break; case FADD: case FSUB: case FMUL: case FDIV: it = pop(); it2 = pop(); pushByFloatMath(seen, it, it2); break; case DADD: case DSUB: case DMUL: case DDIV: case DREM: it = pop(); it2 = pop(); pushByDoubleMath(seen, it, it2); break; case I2B: it = pop(); if (it.getConstant() != null) { it =new Item("I", (byte)constantToInt(it)); } else { it = new Item("I"); } it.setSpecialKind(Item.SIGNED_BYTE); push(it); break; case I2C: it = pop(); if (it.getConstant() != null) { it = new Item("I", (char)constantToInt(it)); } else { it = new Item("I"); } it.setSpecialKind(Item.MASKED_NON_NEGATIVE); push(it); break; case I2L: case D2L:{ it = pop(); Item newValue; if (it.getConstant() != null) { newValue = new Item("J", constantToLong(it)); } else { newValue = new Item("J"); } newValue.setSpecialKind(it.getSpecialKind()); push(newValue); } break; case I2S: it = pop(); if (it.getConstant() != null) { push(new Item("I", (short)constantToInt(it))); } else { push(new Item("I")); } break; case L2I: case D2I: case F2I: it = pop(); if (it.getConstant() != null) { push(new Item("I",constantToInt(it))); } else { push(new Item("I")); } break; case L2F: case D2F: case I2F: it = pop(); if (it.getConstant() != null) { push(new Item("F", (Float)(constantToFloat(it)))); } else { push(new Item("F")); } break; case F2D: case I2D: case L2D: it = pop(); if (it.getConstant() != null) { push(new Item("D", constantToDouble(it))); } else { push(new Item("D")); } break; case NEW: pushBySignature("L" + dbc.getClassConstantOperand() + ";"); break; case NEWARRAY: pop(); signature = "[" + BasicType.getType((byte)dbc.getIntConstant()).getSignature(); pushBySignature(signature); break; // According to the VM Spec 4.4.1, anewarray and multianewarray // can refer to normal class/interface types (encoded in // "internal form"), or array classes (encoded as signatures // beginning with "["). case ANEWARRAY: pop(); signature = dbc.getClassConstantOperand(); if (!signature.startsWith("[")) { signature = "[L" + signature + ";"; } pushBySignature(signature); break; case MULTIANEWARRAY: int dims = dbc.getIntConstant(); while ((dims--) > 0) { pop(); } signature = dbc.getClassConstantOperand(); if (!signature.startsWith("[")) { dims = dbc.getIntConstant(); signature = ""; while ((dims--) > 0) signature += "["; signature += "L" + signature + ";"; } pushBySignature(signature); break; case AALOAD: pop(); it = pop(); pushBySignature(it.getElementSignature()); break; case JSR: push(new Item("")); //? break; case INVOKEINTERFACE: case INVOKESPECIAL: case INVOKESTATIC: case INVOKEVIRTUAL: processMethodCall(dbc, seen); break; default: throw new UnsupportedOperationException("OpCode " + OPCODE_NAMES[seen] + " not supported " ); } } catch (RuntimeException e) { //If an error occurs, we clear the stack and locals. one of two things will occur. //Either the client will expect more stack items than really exist, and so they're condition check will fail, //or the stack will resync with the code. But hopefully not false positives // TODO: log this if (DEBUG) e.printStackTrace(); clear(); } finally { if (exceptionHandlers.get(dbc.getNextPC())) push(new Item()); if (DEBUG) { System.out.println(dbc.getNextPC() + "pc : " + OPCODE_NAMES[seen] + " stack depth: " + getStackDepth()); System.out.println(this); } } } /** * @param it * @return */ private int constantToInt(Item it) { return ((Number)it.getConstant()).intValue(); } /** * @param it * @return */ private float constantToFloat(Item it) { return ((Number)it.getConstant()).floatValue(); } /** * @param it * @return */ private double constantToDouble(Item it) { return ((Number)it.getConstant()).doubleValue(); } /** * @param it * @return */ private long constantToLong(Item it) { return ((Number)it.getConstant()).longValue(); } /** * @param opcode TODO * */ private void handleDcmp(int opcode) { Item it; Item it2; it = pop(); it2 = pop(); if ((it.getConstant() != null) && it2.getConstant() != null) { double d = (Double) it.getConstant(); double d2 = (Double) it.getConstant(); if (Double.isNaN(d) || Double.isNaN(d2)) { if (opcode == DCMPG) push(new Item("I", (Integer)(1))); else push(new Item("I", (Integer)(-1))); } if (d2 < d) push(new Item("I", (Integer) (-1) )); else if (d2 > d) push(new Item("I", (Integer)1)); else push(new Item("I", (Integer)0)); } else { push(new Item("I")); } } /** * @param opcode TODO * */ private void handleFcmp(int opcode) { Item it; Item it2; it = pop(); it2 = pop(); if ((it.getConstant() != null) && it2.getConstant() != null) { float f = (Float) it.getConstant(); float f2 = (Float) it.getConstant(); if (Float.isNaN(f) || Float.isNaN(f2)) { if (opcode == FCMPG) push(new Item("I", (Integer)(1))); else push(new Item("I", (Integer)(-1))); } if (f2 < f) push(new Item("I", (Integer)(-1))); else if (f2 > f) push(new Item("I", (Integer)(1))); else push(new Item("I", (Integer)(0))); } else { push(new Item("I")); } } /** * */ private void handleLcmp() { Item it; Item it2; it = pop(); it2 = pop(); if ((it.getConstant() != null) && it2.getConstant() != null) { long l = (Long) it.getConstant(); long l2 = (Long) it.getConstant(); if (l2 < l) push(new Item("I", (Integer)(-1))); else if (l2 > l) push(new Item("I", (Integer)(1))); else push(new Item("I", (Integer)(0))); } else { push(new Item("I")); } } /** * */ private void handleSwap() { Item i1 = pop(); Item i2 = pop(); push(i1); push(i2); } /** * */ private void handleDup() { Item it; it = pop(); push(it); push(it); } /** * */ private void handleDupX1() { Item it; Item it2; it = pop(); it2 = pop(); push(it); push(it2); push(it); } /** * */ private void handleDup2() { Item it, it2; it = pop(); if (it.getSize() == 2) { push(it); push(it); } else { it2 = pop(); push(it2); push(it); push(it2); push(it); } } /** * */ private void handleDup2X1() { String signature; Item it; Item it2; Item it3; it = pop(); it2 = pop(); signature = it.getSignature(); if (signature.equals("J") || signature.equals("D")) { push(it); push(it2); push(it); } else { it3 = pop(); push(it2); push(it); push(it3); push(it2); push(it); } } /** * */ private void handleDupX2() { String signature; Item it; Item it2; Item it3; it = pop(); it2 = pop(); signature = it2.getSignature(); if (signature.equals("J") || signature.equals("D")) { push(it); push(it2); push(it); } else { it3 = pop(); push(it); push(it3); push(it2); push(it); } } private void processMethodCall(DismantleBytecode dbc, int seen) { String clsName = dbc.getClassConstantOperand(); String methodName = dbc.getNameConstantOperand(); String signature = dbc.getSigConstantOperand(); String appenderValue = null; Item sbItem = null; //TODO: stack merging for trinaries kills the constant.. would be nice to maintain. if ("java/lang/StringBuffer".equals(clsName) || "java/lang/StringBuilder".equals(clsName)) { if ("<init>".equals(methodName)) { if ("(Ljava/lang/String;)V".equals(signature)) { Item i = getStackItem(0); appenderValue = (String)i.getConstant(); } else if ("()V".equals(signature)) { appenderValue = ""; } } else if ("toString".equals(methodName)) { Item i = getStackItem(0); appenderValue = (String)i.getConstant(); } else if ("append".equals(methodName) && signature.indexOf("II)") == -1) { sbItem = getStackItem(1); Item i = getStackItem(0); Object sbVal = sbItem.getConstant();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -