📄 opcodestack.java
字号:
/* * FindBugs - Find bugs in Java programs * Copyright (C) 2004 Dave Brosius <dbrosius@users.sourceforge.net> * Copyright (C) 2003,2004 University of Maryland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package edu.umd.cs.findbugs;import java.util.ArrayList;import java.util.List;import org.apache.bcel.Repository;import org.apache.bcel.classfile.Constant;import org.apache.bcel.classfile.ConstantUtf8;import org.apache.bcel.classfile.ConstantInteger;import org.apache.bcel.classfile.ConstantDouble;import org.apache.bcel.classfile.ConstantFloat;import org.apache.bcel.classfile.ConstantLong;import org.apache.bcel.classfile.ConstantString;import org.apache.bcel.classfile.JavaClass;import org.apache.bcel.classfile.LocalVariableTable;import org.apache.bcel.classfile.LocalVariable;import org.apache.bcel.classfile.Method;import org.apache.bcel.generic.BasicType;import org.apache.bcel.generic.Type;import edu.umd.cs.findbugs.visitclass.Constants2;import edu.umd.cs.findbugs.visitclass.DismantleBytecode;import edu.umd.cs.findbugs.visitclass.LVTHelper;/** * tracks the types and numbers of objects that are currently on the operand stack * throughout the execution of method. To use, a detector should instantiate one for * each method, and call <p>stack.sawOpcode(this,seen);</p> at the bottom of their sawOpcode method. * at any point you can then inspect the stack and see what the types of objects are on * the stack, including constant values if they were pushed. The types described are of * course, only the static types. * There are some outstanding opcodes that have yet to be implemented, I couldn't * find any code that actually generated these, so i didn't put them in because * I couldn't test them: * <ul> * <li>dup2_x2</li> * <li>jsr_w</li> * <li>wide</li> * </ul> */public class OpcodeStack implements Constants2{ private static final boolean DEBUG = Boolean.getBoolean("ocstack.debug"); private List<Item> stack; private List<Item> lvValues; public static class Item { private String signature; private Object constValue; private boolean isNull; public Item(String s) { this(s, null); } public Item(String s, Object v) { signature = s; constValue = v; isNull = false; } public Item() { signature = "Ljava/lang/Object;"; constValue = null; isNull = true; } public JavaClass getJavaClass() throws ClassNotFoundException { String baseSig; if (isPrimitive()) return null; if (isArray()) { baseSig = getElementSignature(); } else { baseSig = signature; } if (baseSig.length() == 0) return null; baseSig = baseSig.substring(1, baseSig.length() - 1); baseSig = baseSig.replace('/', '.'); return Repository.lookupClass(baseSig); } public boolean isArray() { return signature.startsWith("["); } public String getElementSignature() { if (!isArray()) return signature; else { int pos = 0; int len = signature.length(); while (pos < len) { if (signature.charAt(pos) != '[') break; pos++; } return signature.substring(pos); } } public boolean isPrimitive() { return !signature.startsWith("L"); } public String getSignature() { return signature; } public boolean isNull() { return isNull; } public Object getConstant() { return constValue; } } public OpcodeStack() { stack = new ArrayList<Item>(); lvValues = new ArrayList<Item>(); } public void sawOpcode(DismantleBytecode dbc, int seen) { int register; JavaClass cls; String signature; Item it, it2, it3; Constant cons; try { switch (seen) { case ALOAD: pushByLocalObjectLoad(dbc, dbc.getRegisterOperand()); break; case ALOAD_0: case ALOAD_1: case ALOAD_2: case ALOAD_3: pushByLocalObjectLoad(dbc, seen - ALOAD_0); break; case DLOAD: pushByLocalLoad("D", dbc.getRegisterOperand()); break; case DLOAD_0: case DLOAD_1: case DLOAD_2: case DLOAD_3: pushByLocalLoad("D", seen - DLOAD_0); break; case FLOAD: pushByLocalLoad("F", dbc.getRegisterOperand()); break; case FLOAD_0: case FLOAD_1: case FLOAD_2: case FLOAD_3: pushByLocalLoad("F", seen - FLOAD_0); break; case ILOAD: pushByLocalLoad("I", dbc.getRegisterOperand()); break; case ILOAD_0: case ILOAD_1: case ILOAD_2: case ILOAD_3: pushByLocalLoad("I", seen - ILOAD_0); break; case LLOAD: pushByLocalLoad("J", dbc.getRegisterOperand()); break; case LLOAD_0: case LLOAD_1: case LLOAD_2: case LLOAD_3: pushByLocalLoad("J", seen - LLOAD_0); break; case GETSTATIC: pushBySignature(dbc.getSigConstantOperand()); break; case LDC: case LDC_W: case LDC2_W: cons = dbc.getConstantRefOperand(); pushByConstant(dbc, cons); break; case INSTANCEOF: pop(); push(new Item("I")); break; case ARETURN: case DRETURN: case FRETURN: case IFEQ: case IFNE: case IFLT: case IFLE: case IFGT: case IFGE: case IFNONNULL: case IFNULL: case IRETURN: case LOOKUPSWITCH: case LRETURN: case MONITORENTER: case MONITOREXIT: case POP: case PUTSTATIC: case TABLESWITCH: pop(); break; case IF_ACMPEQ: case IF_ACMPNE: case IF_ICMPEQ: case IF_ICMPNE: case IF_ICMPLT: case IF_ICMPLE: case IF_ICMPGT: case IF_ICMPGE: case POP2: case PUTFIELD: pop(2); break; case IALOAD: case SALOAD: pop(2); push(new Item("I")); break; case DUP: it = pop(); push(it); push(it); break; case DUP2: it = pop(); it2 = pop(); push(it2); push(it); push(it2); push(it); break; case DUP_X1: it = pop(); it2 = pop(); push(it); push(it2); push(it); break; case DUP_X2: 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); } break; case DUP2_X1: 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); } break; case ATHROW: case CHECKCAST: case GOTO: case GOTO_W: case IINC: case NOP: case RET: case RETURN: break; case SWAP: Item i1 = pop(); Item i2 = pop(); push(i1); push(i2); break; case ICONST_M1: case ICONST_0: case ICONST_1: case ICONST_2: case ICONST_3: case ICONST_4: case ICONST_5: push(new Item("I", new Integer(seen-ICONST_0))); break; case LCONST_0: case LCONST_1: push(new Item("J", new Long(seen-LCONST_0))); break; case DCONST_0: case DCONST_1: push(new Item("D", new Double(seen-DCONST_0))); break; case FCONST_0: case FCONST_1: case FCONST_2: push(new Item("F", new Float(seen-FCONST_0))); break; case ACONST_NULL: push(new Item()); break; case ASTORE: case DSTORE: case FSTORE: case ISTORE: case LSTORE: pushByLocalStore(dbc.getRegisterOperand()); break; case ASTORE_0: case ASTORE_1: case ASTORE_2: case ASTORE_3: pushByLocalStore(seen - ASTORE_0); break; case DSTORE_0: case DSTORE_1: case DSTORE_2: case DSTORE_3: pushByLocalStore(seen - DSTORE_0); break; case FSTORE_0: case FSTORE_1: case FSTORE_2: case FSTORE_3: pushByLocalStore(seen - FSTORE_0); break; case ISTORE_0: case ISTORE_1: case ISTORE_2: case ISTORE_3: pushByLocalStore(seen - ISTORE_0); break; case LSTORE_0: case LSTORE_1: case LSTORE_2: case LSTORE_3: pushByLocalStore(seen - LSTORE_0); break; case GETFIELD: pop(); push(new Item(dbc.getSigConstantOperand())); break; case ARRAYLENGTH: pop(); push(new Item("I")); break; case BALOAD: case CALOAD: pop(2); push(new Item("I")); break; case DALOAD: pop(2); push(new Item("D")); break; case FALOAD: pop(2); push(new Item("F")); break; case LALOAD: pop(2); push(new Item("J")); break; case AASTORE: case BASTORE: case CASTORE: case DASTORE: case FASTORE: case IASTORE: case LASTORE: case SASTORE: pop(3); break; case BIPUSH: case SIPUSH: push(new Item("I", new Integer((int)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, it, it2); break; case INEG: it = pop(); if (it.getConstant() != null) { push(new Item("I", new Integer(-((Integer)it.getConstant()).intValue()))); } else { push(new Item("I")); } break; case LNEG: it = pop(); if (it.getConstant() != null) { push(new Item("J", new Long(-((Long)it.getConstant()).longValue()))); } else { push(new Item("J"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -