com.markcrocker.purifier
Class StackMapGen

java.lang.Object
  |
  +--com.markcrocker.purifier.StackMapGen
All Implemented Interfaces:
org.apache.bcel.Constants

public class StackMapGen
extends java.lang.Object
implements org.apache.bcel.Constants

A class to facilitate the generation of a StackMap. J2ME devices often have limited resources, so full consistency checking is not desirable. The purpose of a StackMap is to reduce the resources required to verify a class on a J2ME device. It does this by providing the state of the frame at each branch point so that the device can perform the consistency check in a single pass. This way the KVM can verify a class without having to perform slow, iterative, multi-pass data flow analysis.

Version:
0.1
Author:
Mark Crocker

Field Summary
private static int ATTRIBUTELENGTH
           
private static int ATTRIBUTENAMEINDEX
           
private static int BYTECODEOFFSET
           
private static org.apache.log4j.Logger log
           
private static int NUMBEROFLOCALS
           
private static int NUMBEROFSTACKITEMS
           
private static java.lang.String STACKMAP
          Attribute name of a StackMap.
private static int STACKMAPENTRY
          Number of bytes of support data of every StackMapEntry
private  FrameHash stackMapFrames
          A StackMap is a collection of StackMapEntry objects.
private static int STACKMAPHEADER
          Number of bytes in the header data of every StackMap
private static int STACKMAPLENGTH
           
private static int STACKMAPTYPE
          Number of bytes in each StackMapType except ITEM_Object and ObjectNew
private static int STACKMAPTYPEINDEX
           
private static int STACKMAPTYPETYPE
           
 
Fields inherited from interface org.apache.bcel.Constants
AALOAD, AASTORE, ACC_ABSTRACT, ACC_FINAL, ACC_INTERFACE, ACC_NATIVE, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_STATIC, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_TRANSIENT, ACC_VOLATILE, ACCESS_NAMES, ACONST_NULL, ALOAD, ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3, ANEWARRAY, ANEWARRAY_QUICK, ARETURN, ARRAYLENGTH, ASTORE, ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3, ATHROW, ATTR_CODE, ATTR_CONSTANT_VALUE, ATTR_DEPRECATED, ATTR_EXCEPTIONS, ATTR_INNER_CLASSES, ATTR_LINE_NUMBER_TABLE, ATTR_LOCAL_VARIABLE_TABLE, ATTR_PMG, ATTR_SIGNATURE, ATTR_SOURCE_FILE, ATTR_STACK_MAP, ATTR_SYNTHETIC, ATTR_UNKNOWN, ATTRIBUTE_NAMES, BALOAD, BASTORE, BIPUSH, BREAKPOINT, CALOAD, CASTORE, CHECKCAST, CHECKCAST_QUICK, CLASS_TYPE_NAMES, CONSTANT_Class, CONSTANT_Double, CONSTANT_Fieldref, CONSTANT_Float, CONSTANT_Integer, CONSTANT_InterfaceMethodref, CONSTANT_Long, CONSTANT_Methodref, CONSTANT_NameAndType, CONSTANT_NAMES, CONSTANT_String, CONSTANT_Utf8, CONSTRUCTOR_NAME, CONSUME_STACK, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3, DMUL, DNEG, DREM, DRETURN, DSTORE, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3, FMUL, FNEG, FREM, FRETURN, FSTORE, FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3, FSUB, GETFIELD, GETFIELD_QUICK, GETFIELD_QUICK_W, GETFIELD2_QUICK, GETSTATIC, GETSTATIC_QUICK, GETSTATIC2_QUICK, GOTO, GOTO_W, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILLEGAL_OPCODE, ILLEGAL_TYPE, ILOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, IMPDEP1, IMPDEP2, IMUL, INEG, INSTANCEOF, INSTANCEOF_QUICK, INT2BYTE, INT2CHAR, INT2SHORT, INTERFACES_IMPLEMENTED_BY_ARRAYS, INVOKEINTERFACE, INVOKEINTERFACE_QUICK, INVOKENONVIRTUAL, INVOKENONVIRTUAL_QUICK, INVOKESPECIAL, INVOKESTATIC, INVOKESTATIC_QUICK, INVOKESUPER_QUICK, INVOKEVIRTUAL, INVOKEVIRTUAL_QUICK, INVOKEVIRTUAL_QUICK_W, INVOKEVIRTUALOBJECT_QUICK, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3, ISUB, ITEM_Bogus, ITEM_Double, ITEM_Float, ITEM_InitObject, ITEM_Integer, ITEM_Long, ITEM_NAMES, ITEM_NewObject, ITEM_Null, ITEM_Object, IUSHR, IXOR, JSR, JSR_W, KNOWN_ATTRIBUTES, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDC_QUICK, LDC_W, LDC_W_QUICK, LDC2_W, LDC2_W_QUICK, LDIV, LLOAD, LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3, LMUL, LNEG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3, LSUB, LUSHR, LXOR, MAJOR, MAJOR_1_1, MAJOR_1_2, MAJOR_1_3, MAX_ACC_FLAG, MAX_BYTE, MAX_CODE_SIZE, MAX_CP_ENTRIES, MAX_SHORT, MINOR, MINOR_1_1, MINOR_1_2, MINOR_1_3, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, MULTIANEWARRAY_QUICK, NEW, NEW_QUICK, NEWARRAY, NO_OF_OPERANDS, NOP, OPCODE_NAMES, POP, POP2, PRODUCE_STACK, PUSH, PUTFIELD, PUTFIELD_QUICK, PUTFIELD_QUICK_W, PUTFIELD2_QUICK, PUTSTATIC, PUTSTATIC_QUICK, PUTSTATIC2_QUICK, RESERVED, RET, RETURN, SALOAD, SASTORE, SHORT_TYPE_NAMES, SIPUSH, STATIC_INITIALIZER_NAME, SWAP, SWITCH, T_ADDRESS, T_ARRAY, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_OBJECT, T_REFERENCE, T_SHORT, T_UNKNOWN, T_VOID, TABLESWITCH, TYPE_NAMES, TYPE_OF_OPERANDS, UNDEFINED, UNPREDICTABLE, WIDE
 
Constructor Summary
StackMapGen()
           
 
Method Summary
static int calculateStackMapLength(org.apache.bcel.classfile.StackMapEntry[] stackMapEntries)
          The StackMap constructor requires the length of the StackMap, which is not trivial to calculate.
private  org.apache.bcel.classfile.StackMap constructStackMap(java.util.Hashtable stackMapFrames, org.apache.bcel.generic.ConstantPoolGen cpg)
          A StackMap cannot simply be constructed from a Vector of StackMapEntry's.
private  void consumeStack(org.apache.bcel.generic.Instruction instruction, OperandStack os, org.apache.bcel.generic.ConstantPoolGen cpg)
          BCEL instructions already know how many stack items they consume.
 org.apache.bcel.classfile.StackMap generateStackMap(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.ConstantPoolGen cpg)
          Generate a StackMap for a particular method.
private  void getField(Frame frame, org.apache.bcel.generic.ConstantPoolGen cpg, org.apache.bcel.generic.Type type)
           
static int getNameIndex(org.apache.bcel.generic.ConstantPoolGen cpg)
          The StackMap constructor requires the index in the ConstantPool for the name of the StackMap attribute.
private  void illegalInstruction(org.apache.bcel.generic.InstructionHandle ih)
           
private  void invokeInstruction(org.apache.bcel.generic.InvokeInstruction instruction, OperandStack os, org.apache.bcel.classfile.StackMapType[] stackArgs, org.apache.bcel.generic.ConstantPoolGen cpg)
           
private  void lLoadInstruction(Frame frame, int index)
           
private  void loadInstruction(Frame frame, int index)
           
static void main(java.lang.String[] argv)
           
private  void nonCLDCInstruction(org.apache.bcel.generic.InstructionHandle ih)
           
private  void storeInstruction(Frame frame, int index)
           
private  void updateFrame(org.apache.bcel.generic.InstructionList il, org.apache.bcel.generic.InstructionHandle ih, Frame frame, Frame storedFrame, org.apache.bcel.generic.ConstantPoolGen cpg)
           
 
Methods inherited from class java.lang.Object
, clone, equals, finalize, getClass, hashCode, notify, notifyAll, registerNatives, toString, wait, wait, wait
 

Field Detail

log

private static org.apache.log4j.Logger log

STACKMAP

private static final java.lang.String STACKMAP
Attribute name of a StackMap. Used in the constant pool

ATTRIBUTENAMEINDEX

private static final int ATTRIBUTENAMEINDEX

ATTRIBUTELENGTH

private static final int ATTRIBUTELENGTH

STACKMAPLENGTH

private static final int STACKMAPLENGTH

STACKMAPHEADER

private static final int STACKMAPHEADER
Number of bytes in the header data of every StackMap

BYTECODEOFFSET

private static final int BYTECODEOFFSET

NUMBEROFLOCALS

private static final int NUMBEROFLOCALS

NUMBEROFSTACKITEMS

private static final int NUMBEROFSTACKITEMS

STACKMAPENTRY

private static final int STACKMAPENTRY
Number of bytes of support data of every StackMapEntry

STACKMAPTYPETYPE

private static final int STACKMAPTYPETYPE

STACKMAPTYPEINDEX

private static final int STACKMAPTYPEINDEX

STACKMAPTYPE

private static final int STACKMAPTYPE
Number of bytes in each StackMapType except ITEM_Object and ObjectNew

stackMapFrames

private FrameHash stackMapFrames
A StackMap is a collection of StackMapEntry objects. StackMapGen stores them internally as a FrameHash.
Constructor Detail

StackMapGen

public StackMapGen()
Method Detail

generateStackMap

public org.apache.bcel.classfile.StackMap generateStackMap(org.apache.bcel.generic.MethodGen mg,
                                                           org.apache.bcel.generic.ConstantPoolGen cpg)
Generate a StackMap for a particular method.
Parameters:
mg - is the method generator for the method of interest.
cpg - is the constant pool generator for the class that the method is a part of. Although cpg could be derived from mg, it is passed explicitly to this method because there are possible side effects to cpg if a new "StackMap" entry is required in the constant pool. See the getNameIndex method for details.

constructStackMap

private org.apache.bcel.classfile.StackMap constructStackMap(java.util.Hashtable stackMapFrames,
                                                             org.apache.bcel.generic.ConstantPoolGen cpg)
A StackMap cannot simply be constructed from a Vector of StackMapEntry's. This method converts the Vector into a sorted array, calculates the StackMap length and gets or generates a constant pool index for the "StackMap" attribute name. Finally, the StackMap is generated from all of this data. Beware that there are side effects on cpg. See the getNameIndex method for details.

calculateStackMapLength

public static int calculateStackMapLength(org.apache.bcel.classfile.StackMapEntry[] stackMapEntries)
The StackMap constructor requires the length of the StackMap, which is not trivial to calculate. The calculateStackMapLength method does that calculation.

getNameIndex

public static int getNameIndex(org.apache.bcel.generic.ConstantPoolGen cpg)
The StackMap constructor requires the index in the ConstantPool for the name of the StackMap attribute. In the case of an already preverfied J2ME class, this entry already exists and merely has to be found. Also, if StackMaps have been created for other methods in this class, then the entry will already exist. Otherwise, the string "StackMap" will have to be added to the ConstantPool and its index returned. In this last case, this method will have the side effect of changing the ConstantPoolGen, cpg.
Parameters:
cpg - The constant pool generator of the class that the StackMap is being generated for. Note that if there is no entry for "StackMap" in the constant pool, then one will be added to cpg. Consequently a possible side effect of this method is a change to cpg. So make sure that the same cpg is used for every method in a given class and that a new constant pool is generated from cpg and written to the class at the same time that the corresponding StackMap is added to the class.
Returns:
index in the constant pool of the UTF-8 string "StackMap".

updateFrame

private void updateFrame(org.apache.bcel.generic.InstructionList il,
                         org.apache.bcel.generic.InstructionHandle ih,
                         Frame frame,
                         Frame storedFrame,
                         org.apache.bcel.generic.ConstantPoolGen cpg)

nonCLDCInstruction

private void nonCLDCInstruction(org.apache.bcel.generic.InstructionHandle ih)

illegalInstruction

private void illegalInstruction(org.apache.bcel.generic.InstructionHandle ih)

lLoadInstruction

private void lLoadInstruction(Frame frame,
                              int index)

loadInstruction

private void loadInstruction(Frame frame,
                             int index)

storeInstruction

private void storeInstruction(Frame frame,
                              int index)

getField

private void getField(Frame frame,
                      org.apache.bcel.generic.ConstantPoolGen cpg,
                      org.apache.bcel.generic.Type type)

invokeInstruction

private void invokeInstruction(org.apache.bcel.generic.InvokeInstruction instruction,
                               OperandStack os,
                               org.apache.bcel.classfile.StackMapType[] stackArgs,
                               org.apache.bcel.generic.ConstantPoolGen cpg)

consumeStack

private void consumeStack(org.apache.bcel.generic.Instruction instruction,
                          OperandStack os,
                          org.apache.bcel.generic.ConstantPoolGen cpg)
BCEL instructions already know how many stack items they consume. This method uses that information to remove the appropriate number of items off of the OperandStack in the Frame.

main

public static void main(java.lang.String[] argv)