FileDocCategorySizeDatePackage
MethodInfo.javaAPI DocphoneME MR2 API (J2ME)31588Wed May 02 17:59:48 BST 2007components

MethodInfo

public class MethodInfo extends ClassMemberInfo implements jcc.Const

Fields Summary
public int
argsSize
public int
stack
public int
locals
public int
methodTableIndex
public byte[]
code
private Attribute[]
methodAttributes
public CodeAttribute
codeAttribute
public Attribute[]
codeAttributes
public ExceptionEntry[]
exceptionTable
public ClassConstant[]
exceptionsThrown
private boolean
checkedDebugTables
private LineNumberTableEntry[]
lineNumberTable
private LocalVariableTableEntry[]
localVariableTable
public StackMapFrame[]
stackMapTable
public vm.VMMethodInfo
vmMethodInfo
public MethodInfo[]
targetMethods
public int[]
ldcInstructions
The following are arrays of indexes into the code array of references to the constant pool: ldcInstructions lists the instructions with a one-byte index. wideConstantRefInstructions lists the instructions with a two-byte index. In each case, the index is that of the opcode: the actual reference begins with the following byte. Entries of value -1 are ignored.
public int[]
wideConstantRefInstructions
private String
nativeName
private static Hashtable
methodAttributeTypes
Constructors Summary
public MethodInfo(int name, int sig, int access, ClassInfo p)


               
	super( name, sig, access, p );
    
Methods Summary
private static final intat(byte[] codeBytes, int index)
Return the byte stored at a given index from the offset within code bytes

    	return codeBytes[index] & 0xFF;
    
public voidcountConstantReferences(ConstantObject[] table, boolean isRelocatable)

	super.countConstantReferences();
	Attribute.countConstantReferences( methodAttributes, isRelocatable );
	Attribute.countConstantReferences( codeAttributes, isRelocatable );
	if ( code == null ) return; // no code, no relocation
	if ( ldcInstructions != null ){
	    int list[] = ldcInstructions;
	    int n = list.length;
	    for (int i = 0; i < n; i++){
		int loc = list[i];
		if ( loc==-1 ) continue;
		table[ (int)code[loc+1]&0xff ].incReference();
	    }
	}
	if ( wideConstantRefInstructions != null ){
	    int list[] = wideConstantRefInstructions;
	    int n = list.length;
	    for (int i = 0; i < n; i++){
		int loc = list[i];
		if ( loc==-1 ) continue;
		table[ getUnsignedShort(loc+1) ].incReference();
	    }
	}
    
public voiddisassemble()

 
        System.out.println(disassemble(code, 0, code.length));
    
public java.lang.Stringdisassemble(int start, int end)

 
	return disassemble(code, start, end);
    
public static java.lang.Stringdisassemble(byte[] codeBytes, int start, int end)

 
	// Output goes into a string
	StringWriter sw = new StringWriter();
	PrintWriter output = new PrintWriter(sw);
	
	for (int offset = start; offset < end; ) {
	    int opcode = at(codeBytes, offset);

	    if (offset > start) 
	        output.print("; ");
            
            output.print(opcodeName(opcode));

	    switch (opcode) {
	    case opc_aload: case opc_astore:
	    case opc_fload: case opc_fstore:
	    case opc_iload: case opc_istore:
	    case opc_lload: case opc_lstore:
	    case opc_dload: case opc_dstore:
	    case opc_ret:
		output.print(" " + at(codeBytes, offset+1));
		offset += 2;
		break;
		    
	    case opc_iinc:
		output.print(" " + at(codeBytes, offset+1)  + " " + 
			     (byte) at(codeBytes, offset +2));
		offset += 3;
		break;

	    case opc_newarray:
		switch (at(codeBytes, offset+1)) {
		case T_INT:    output.print(" int");    break;
		case T_LONG:   output.print(" long");   break;
		case T_FLOAT:  output.print(" float");  break;
		case T_DOUBLE: output.print(" double"); break;
		case T_CHAR:   output.print(" char");   break;
		case T_SHORT:  output.print(" short");  break;
		case T_BYTE:   output.print(" byte");   break;
		case T_BOOLEAN:output.print(" boolean");   break;
		default:             output.print(" BOGUS"); break;
		}
		offset += 2;
		break;

	    case opc_anewarray_fast:
	    case opc_anewarray: {
		int index =  shortAt(codeBytes, offset+1);
		output.print(" class #" + index + " ");
		offset += 3;
		break;
	    }
		      
	    case opc_sipush:
		output.print(" " + (short) shortAt(codeBytes, offset+1));
		offset += 3;
		break;

	    case opc_bipush:
		output.print(" " + (byte) at(codeBytes, offset+1));
		offset += 2;
		break;

	    case opc_ldc: {
		int index = at(codeBytes, offset+1);
		output.print(" #" + index + " ");
		offset += 2;
		break;
	    }

            case opc_getstatic_fast:
            case opc_getstaticp_fast:
            case opc_getstatic2_fast:
            case opc_putstatic_fast:
            case opc_putstatic2_fast:
            case opc_unused_d5:
            case opc_invokevirtual_fast:
            case opc_invokespecial_fast:
            case opc_invokestatic_fast:
            case opc_invokeinterface_fast:
            case opc_new_fast:
            case opc_multianewarray_fast:
            case opc_checkcast_fast:
            case opc_instanceof_fast:
	    case opc_ldc_w: case opc_ldc2_w:
	    case opc_instanceof: case opc_checkcast:
	    case opc_new:
	    case opc_putstatic: case opc_getstatic:
	    case opc_putfield: case opc_getfield:
	    case opc_invokevirtual:
	    case opc_invokespecial:
	    case opc_invokestatic: {
		int index = shortAt(codeBytes, offset+1);
		output.print(" #" + index + " ");
		offset += 3;
		break;
	    }

            case opc_getfield_fast:
            case opc_getfieldp_fast:
            case opc_getfield2_fast:
            case opc_putfield_fast:
            case opc_putfield2_fast: { 
		int index = at(codeBytes, offset+1);
		output.print(" [" + index + "] ");
		offset += 3;
		break;
	    }

	    case opc_jsr: case opc_goto:
	    case opc_ifeq: case opc_ifge: case opc_ifgt:
	    case opc_ifle: case opc_iflt: case opc_ifne:
	    case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge:
	    case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt:
	    case opc_if_acmpeq: case opc_if_acmpne:
	    case opc_ifnull: case opc_ifnonnull: {
		int target = offset + (short) shortAt(codeBytes,offset+1);
		output.print(" " + target);
		offset += 3;
		break;
	    }

	    default:
		offset += opcodeLength(codeBytes, offset);
		break;
	    }
	}
        
	output.close();
	return sw.toString();
    
public voidexternalize(ConstantPool p)

	super.externalize( p );
	Attribute.externalizeAttributes( methodAttributes, p );
	Attribute.externalizeAttributes( codeAttributes, p );
    
public voidfindConstantReferences()

	if ( code == null ) return; // no code, no references.
	int 	ldc[]  = new int[ code.length / 2 ];
	int 	wide[] = new int[ code.length / 3 ];
	int	nldc   = 0;
	int	nwide  = 0;
	int	ncode  = code.length;
	int	opcode;
	for( int i = 0; i < ncode; /*nothing*/){
	    switch (opcode = (int)code[i]&0xff) {
	    case opc_tableswitch:
		i = (i + 4) & ~3;
		int low = getInt( i+4);
		int high = getInt( i+8);
		i += (high - low + 1) * 4 + 12;
		break;

	    case opc_lookupswitch:
		i = (i + 4) & ~3;
		int pairs = getInt(i+4);
		i += pairs * 8 + 8;
		break;

	    case opc_wide:
		switch ((int)code[i+1]&0xff) {
		case opc_aload:
		case opc_iload:
		case opc_fload:
		case opc_lload:
		case opc_dload:
		case opc_istore:
		case opc_astore:
		case opc_fstore:
		case opc_lstore:
		case opc_dstore:
		case opc_ret:
		    i += 4;
		    break;

		case opc_iinc:
		    i += 6;
		    break;

		default:
		    throw new DataFormatException( parent.className + "." +
			name.string + ": unknown wide " +
			"instruction: " + code[i+1] );
		}
		break;
	    case opc_ldc:
		ldc[nldc++] = i;
		i += opcLengths[opcode];
		break;
	    case opc_ldc_w:
	    case opc_ldc2_w:
	    case opc_getstatic:
	    case opc_putstatic:
	    case opc_getfield:
	    case opc_putfield:
	    case opc_invokevirtual:
	    case opc_invokespecial:
	    case opc_invokestatic:
	    case opc_invokeinterface:
	    case opc_new:
	    case opc_anewarray:
	    case opc_checkcast:
	    case opc_instanceof:
	    case opc_multianewarray:

            case opc_getstatic_fast:
            case opc_getstaticp_fast:
            case opc_getstatic2_fast:
            case opc_putstatic_fast:
            case opc_putstatic2_fast:
            case opc_invokevirtual_fast:
            case opc_invokespecial_fast:
            case opc_invokestatic_fast:
            case opc_invokeinterface_fast:
            case opc_new_fast:
            case opc_anewarray_fast:
            case opc_multianewarray_fast:
            case opc_checkcast_fast:
            case opc_instanceof_fast:
		wide[nwide++] = i;
		i += opcLengths[opcode];
		break;
	    default: 
		i +=  opcLengths[opcode];
		break;
	    }
	}
	// not knowing any better, we allocated excess capacity.
	// allocate and fill appropriately-sized arrays.
	ldcInstructions = new int[ nldc ];
	System.arraycopy( ldc, 0, ldcInstructions, 0, nldc );
	ldc = null;
	wideConstantRefInstructions = new int[ nwide ];
	System.arraycopy( wide, 0, wideConstantRefInstructions, 0, nwide );
	wide = null;
    
public ClassConstant[]getExceptionsThrown()

	return exceptionsThrown;
    
private static intgetInt(byte[] code, int w)

 
	return	(  (int)code[w]   << 24 ) |
		(( (int)code[w+1] &0xff ) << 16 ) |
		(( (int)code[w+2] &0xff ) << 8 ) |
		 ( (int)code[w+3] &0xff );
    
public intgetInt(int w)

	return	getInt(code, w);
    
private java.lang.StringgetJNIName()

 
        ClassInfo ci = parent;
        String classname = ci.className;
	String methodname = this.name.string;
	int nmethods = ci.methods.length;
	String typeName = null;	// by default, don't need type
	for (int j = 0; j < nmethods; j ++ ){
	    MethodInfo m = ci.methods[j];
	    if ((m != this) && ( (m.access&Const.ACC_NATIVE) != 0 )) {
	        if (m.name.equals(this.name)) {
		    // Two native methods with the same name.  Need type name
		    typeName = this.type.string;
		    break;
		}
	    }
	} 
	return Util.convertToJNIName(classname, methodname, typeName);
    
public java.lang.StringgetJNIReturnType()

	return Util.parseReturnType(this.type.string);
    
public java.util.BitSetgetLabelTargets()

 
        java.util.BitSet result = new java.util.BitSet();
	int ncode  = code.length;
	int nextpc;

	for(int pc = 0; pc < ncode; pc = nextpc) {
	    nextpc = pc + opcodeLength(pc);
	    int opcode = (int)code[pc]&0xff;
	    switch (opcode) {
	      
	    case opc_tableswitch: 
	    case opc_lookupswitch: 
	        int i = (pc + 4) & ~3;
		int delta = (opcode == opc_tableswitch) ? 4 : 8;
		result.set(pc + getInt(i)); // default
		for (i = i + 12; i < nextpc; i += delta)
		    result.set(pc + getInt(i));
		break;

	    case opc_jsr: 
	        result.set(pc + 3);
	    case opc_goto:
	    case opc_ifeq: case opc_ifge: case opc_ifgt:
	    case opc_ifle: case opc_iflt: case opc_ifne:
	    case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge: 
	    case opc_if_icmplt: case opc_if_icmpgt: case opc_if_icmple: 
	    case opc_if_acmpeq: case opc_if_acmpne:
	    case opc_ifnull: case opc_ifnonnull:
	        result.set(pc + getShort(pc + 1)); 
		break;

	    case opc_jsr_w:
	        result.set(pc + 5);
	    case opc_goto_w:
	        result.set(pc + getInt(pc + 1)); 
		break;
	    }
	}
	return result;
    
public LineNumberTableEntry[]getLineNumberTable()

	if ( !checkedDebugTables ){
	    initializeClassDebugTables();
	    checkedDebugTables = true;
	}
	return lineNumberTable;
    
public LocalVariableTableEntry[]getLocalVariableTable()

	if ( !checkedDebugTables ){
	    initializeClassDebugTables();
	    checkedDebugTables = true;
	}
	return localVariableTable;
    
public java.lang.StringgetNativeName(boolean isJNI)

 
        if (nativeName == null) { 
	    nativeName = isJNI ? getJNIName() : getOldNativeName();
	}
	return nativeName;
    
private java.lang.StringgetOldNativeName()

 
        ClassInfo ci = parent;
	String methodname = this.name.string;
	StringBuffer sbuf = new StringBuffer(/*NOI18N*/"Java_")
	                          .append(ci.getGenericNativeName())
	                          .append('_");
	if (methodname.indexOf('_") == -1) {
	    // optimization.  Most methods don't have an _ in them
	    sbuf.append(methodname);
	} else { 
	    for (int i = 0; i < methodname.length(); i++) { 
	      if (methodname.charAt(i) == '_") {
		  sbuf.append(/*NOI18N*/"_0005f");
	      } else {
		  sbuf.append(methodname.charAt(i));
	      }
	    }
	}
	sbuf.append("_stub");
	return sbuf.toString();
    
public intgetShort(int w)

	return	(( (int)code[w]) << 8 ) | ( (int)code[w+1] &0xff );
    
public intgetUnsignedShort(int w)

	return	(( (int)code[w] &0xff ) << 8 ) | ( (int)code[w+1] &0xff );
    
public booleanhasLineNumberTable()

	if ( !checkedDebugTables ){
	    initializeClassDebugTables();
	    checkedDebugTables = true;
	}
	return (lineNumberTable != null) && (lineNumberTable.length != 0);
    
public booleanhasLocalVariableTable()

	if ( !checkedDebugTables ){
	    initializeClassDebugTables();
	    checkedDebugTables = true;
	}
	return (localVariableTable != null) && (localVariableTable.length != 0);
    
public voidinitializeClassDebugTables()

	int nattr = (codeAttributes == null) ? 0 : codeAttributes.length;
	// parse code attributes
	for (int i = 0; i < nattr; i++) {
	    Attribute a = codeAttributes[i];
	    if (a.name.string.equals("LineNumberTable")) {
		lineNumberTable = ((LineNumberTableAttribute)a).data;
	    }
	    if (a.name.string.equals("LocalVariableTable")) {
		localVariableTable = ((LocalVariableTableAttribute)a).data;
	    }
	    if (a.name.string.equals("StackMap")) {
		stackMapTable = ((StackMapAttribute)a).data;
	    }

	}
    
public intnExceptionsThrown()

	return ( exceptionsThrown == null ) ? 0 : exceptionsThrown.length;
    
private static intopcodeLength(byte[] code, int pc)

        int old_pc;
	int opcode = (int)code[pc]&0xff;
        switch (opcode) {

	case opc_tableswitch: 
	    old_pc = pc;
  	    pc = (pc + 4) & ~3;
	    int low = getInt(code, pc + 4);
	    int high = getInt(code, pc + 8);
	    pc += (high - low + 1) * 4 + 12;
	    return pc - old_pc;

	case opc_lookupswitch:
	    old_pc = pc;
	    pc = (pc + 4) & ~3;
	    int pairs = getInt(code, pc + 4);
	    pc += pairs * 8 + 8;
	    return pc - old_pc;

	case opc_wide:
	    if (((int)code[pc + 1]&0xff) == opc_iinc) 
	        return 6;
	    return 4;

	default:
	    return opcLengths[opcode];
	}
    
public intopcodeLength(int pc)

 
        return opcodeLength(code, pc);
    
public static java.lang.StringopcodeName(int opcode)

 
	return opcNames[opcode];
    
private voidputInt(byte[] array, int offset, int val)

        array[offset] =   (byte) ((val >> 24) & 0xFF);
        array[offset+1] = (byte) ((val >> 16) & 0xFF);
        array[offset+2] = (byte) ((val >> 8) & 0xFF);
        array[offset+3] = (byte) (val & 0xFF);
    
private voidputShort(int w, short v)

	code[w]   = (byte)(v>>>8);
	code[w+1] = (byte)v;
    
voidreadAttributes(java.io.DataInput in, ConstantObject[] locals, ConstantObject[] globals, boolean readCode)


     
	methodAttributeTypes.put( "Code", CodeAttributeFactory.instance );
	methodAttributeTypes.put( "Exceptions", ExceptionsAttributeFactory.instance );
    

	methodAttributes = Attribute.readAttributes( in, locals, globals, methodAttributeTypes, false );

	// oops, we read the code.
	// we'll fix this someday.

	//
	// parse special attributes
	//
	if ( methodAttributes != null ){
	    for ( int i = 0; i < methodAttributes.length; i ++ ){
		Attribute a = methodAttributes[i];
		if (a.name.string.equals("Code") ) {
		    CodeAttribute ca = (CodeAttribute)a;
		    this.locals = ca.locals;
		    this.stack  = ca.stack;
		    this.code   = ca.code;
		    this.exceptionTable = ca.exceptionTable;
		    this.codeAttributes = ca.codeAttributes;
		    this.codeAttribute = ca;
		} else if (a.name.string.equals("Exceptions") ) {
		    this.exceptionsThrown = ((ExceptionsAttribute)a).data;
		}
	    }
	}

    
public static components.MethodInforeadMethod(java.io.DataInput in, ClassInfo p, boolean readCode)

	int access = in.readUnsignedShort();
	int name   = in.readUnsignedShort();
	int sig    = in.readUnsignedShort();
	MethodInfo m = new MethodInfo( name, sig, access, p );
	// the bad thing is, we really cannot go far
	// without resolving. So we resolve here.
	m.resolve( p.symbols );

	m.argsSize = Util.argsSize(m.type.string);
	if ((m.access & ACC_STATIC) == 0) {
	    m.argsSize++;
	}

	m.readAttributes( in, p.constants, p.symbols, readCode );
	return m;
    
public voidrelocateAndPackCode(ConstantObject[] co)


        if (code == null)
            return;

        int opcode, adjustment = 0;
        int newOffsets[] = new int[code.length];
        int indexByPC[] = new int[code.length];

        // First figure out where we'll have to insert extra bytes in
        // order to fit opc_ldc_w instead of opc_ldc instructions.
        for (int pc = 0, pcindex = 0; pc < code.length;
		 pc = pc + opcodeLength(pc), pcindex++) {
            opcode = (int) code[pc]&0xFF;
            newOffsets[pcindex] = pc + adjustment;
            indexByPC[pc] = pcindex;

          /*******
           * switch (opcode) {
           *    case opc_ldc: {
           *        // a conversion table which maps pcValue to new index.
           *        int oldindex = (int)(code[pc+1] & 0xFF);
           *        int index = co[oldindex].index;
           *
           *        if (index >= 0x100)
           *            adjustment++;
           *        break;
           *    }
           *
           *
	   *  case opc_ldc_w: {
	   *      // a conversion table which maps pcValue to new index.
           *      int oldindex = (int)(((code[pc+1]&0xFF) << 8)
	   *    		 | (code[pc+2]&0xFF));
	   *      int index = co[oldindex].index;
           *
           *      if (index < 0x100)
           *          adjustment--;
           *      break;
           *  }
           *
           *
           *
           *  case opc_goto: {
           *      // Calculate the displacement, sign extend high byte
           *      int displ = (code[pc+1] << 8) | (code[pc+2] & 0xFF);
           *
	   *      if (displ == 3) {
	   *          adjustment -= 3; // remove no-use goto's.
	   *      }
	   *      break;
	   *  }
           *
	   *  case opc_nop: {
	   *      adjustment--; // remove
	   *      break;
	   *  }
           *
           *
	   *  case opc_tableswitch:
	   *  case opc_lookupswitch: {
	   *      int oldExtraPC = (( pc + 4 ) & ~3);
	   *      int newExtraPC = (( pc + adjustment + 4) & ~3);
	   *      adjustment = newExtraPC - oldExtraPC;
	   *      break;
	   *  }
           * }
           *******/
        }

        // Now copy the code to the new location. At the same
        // time, we adjust all branch targets.
        byte newCode[] = new byte[code.length + adjustment];

        for (int pc = 0, pcindex = 0; pc < code.length;
		 pc = pc + opcodeLength(pc), pcindex++) {
            int outPos = newOffsets[pcindex];
	    int inPos = pc;

	    opcode = (int) code[pc]&0xFF;

            for (int i = 0; i < opcodeLength(pc); i++) {
                newCode[outPos + i] = code[pc + i];
            }

            switch (opcode) {
	      case opc_ldc: {
		  int oldindex = (int)(code[pc+1] & 0xFF);
                  int index = co[oldindex].index;
                  if (index >= 0x100) {
                      new RuntimeException("load constant overflow");
                  }
                  newCode[outPos +1] = (byte) index ;
                  break;
              }

         /****
	  *   // Remapping branches
	  *   case opc_ifeq:
          *   case opc_ifne:
          *   case opc_iflt:
          *   case opc_ifge:
          *   case opc_ifgt:
          *   case opc_ifle:
          *   case opc_if_icmpeq:
          *   case opc_if_icmpne:
          *   case opc_if_icmplt:
          *   case opc_if_icmpge:
          *   case opc_if_icmpgt:
          *   case opc_if_icmple:
          *   case opc_if_acmpeq:
          *   case opc_if_acmpne:
          *   case opc_ifnull:
          *   case opc_ifnonnull:
          *   case opc_goto:
          *   case opc_jsr: {
          *       // Calculate the displacement, sign extend high byte
          *       int displ = (code[pc+1] << 8) | (code[pc+2] & 0xFF);
          *
          *      *  if (displ == 3 && opcode == opc_goto) {
	  *      *     break;
	  *      * }
          *

          *       int branchDest = pc + displ;
          *
	  *       if ((code[branchDest] & 0xFF) == opc_goto) {
          *           // We're branching to a goto.  We can just branch to
	  *           // where the goto was going.
	  *           branchDest +=
	  *     	(code[branchDest+1] << 8) | (code[branchDest+2] & 0xFF);
	  *       }
          *       int newDest = newOffsets[indexByPC[branchDest]] - outPos;
          *       newCode[outPos+1] = (byte) ((newDest >> 8) & 0xFF);
          *       newCode[outPos+2] = (byte) (newDest & 0xFF);
          *       break;
          *   }
          *
	  *   case opc_tableswitch: {
	  *       newCode[outPos] = code[pc];
	  *       outPos = (outPos + 4) & ~3;
	  *       inPos = (inPos + 4) & ~3;
          *
	  *       // Update the default destination
	  *       int oldDest = getInt(inPos) + pc;
	  *       int newDest = newOffsets[indexByPC[oldDest]]
	  *     		- newOffsets[pcindex];
	  *       putInt(newCode, outPos, newDest);
          *
	  *       // Update each of the destinations in the table
	  *       int low = getInt(inPos+4);
	  *       int high = getInt(inPos+8);
	  *       putInt(newCode, outPos+4, low);
	  *       putInt(newCode, outPos+8, high);
	  *       for (int j = 0; j <= high-low; j++) {
          *           int offset = j * 4 + 12;
          *           oldDest = getInt(inPos + offset) + pc;
          *           newDest = newOffsets[indexByPC[oldDest]]
	  *     		- newOffsets[pcindex];
	  *           putInt(newCode, outPos + offset, newDest);
          *       }
	  *       break;
          *   }
          *
	  *   case opc_lookupswitch: {
	  *       newCode[outPos] = code[pc];
	  *       // 0-3 byte pads
	  *       outPos = (outPos + 4) & ~3;
	  *       inPos = (inPos + 4) & ~3;
          *
	  *       // Update the default destination
          *       int oldDest = getInt(inPos) + pc;
          *       int newDest = newOffsets[indexByPC[oldDest]]
	  *     	        - newOffsets[pcindex];
          *       putInt(newCode, outPos, newDest);
          *
          *       // Update each of the pairs of destinations in the list
          *       int pairs = getInt(inPos+4);
          *       putInt(newCode, outPos+4, pairs);
          *       for (int j = 0; j < pairs; j++) {
          *           int offset = (j + 1) * 8;
          *
          *           // First copy the value
          *           putInt(newCode, outPos + offset,
          *                  getInt(inPos + offset));
          *           offset += 4;
          *
          *           // Now adjust the destination
          *           oldDest = getInt(inPos + offset) + pc;
          *           newDest = newOffsets[indexByPC[oldDest]]
	  *     		- newOffsets[pcindex];
          *           putInt(newCode, outPos + offset, newDest);
          *       }
	  *       break;
	  *   }
          ********/

	      // Byte-codes with constant pool access. Remap to new indices
	      case opc_getfield:
	      case opc_checkcast:
	      case opc_getstatic:
	      case opc_instanceof:
	      case opc_ldc2_w:
	      case opc_new:
	      case opc_putfield:
	      case opc_putstatic:
	      case opc_invokevirtual:
	      case opc_invokestatic:
	      case opc_invokespecial:
              case opc_getstatic_fast:
              case opc_getstaticp_fast:
              case opc_getstatic2_fast:
              case opc_putstatic_fast:
              case opc_putstatic2_fast:
              case opc_invokevirtual_fast:
              case opc_invokespecial_fast:
              case opc_invokestatic_fast:
              case opc_anewarray_fast:
              case opc_checkcast_fast:
              case opc_instanceof_fast:
	      case opc_multianewarray:
	      case opc_multianewarray_fast:
	      case opc_invokeinterface:
 	      case opc_invokeinterface_fast:
              case opc_ldc_w: {
		  int oldindex = (int)(((code[pc+1]&0xFF) << 8)
                                   | (code[pc+2]&0xFF));
                  int index = co[oldindex].index;
		  newCode[outPos] = (byte) opcode;
		  newCode[outPos+1] = (byte) ((index >> 8) & 0xFF);
                  newCode[outPos+2] = (byte) (index & 0xFF);
                  break;
	      }
            }
        }

        // Update the exception table
        for (int i = 0; i < exceptionTable.length; i++) {
            ExceptionEntry e = exceptionTable[i];
            e.startPC = newOffsets[indexByPC[e.startPC]];
            e.endPC = newOffsets[indexByPC[e.endPC]];
            e.handlerPC = newOffsets[indexByPC[e.handlerPC]];
        }

        // Update the line number table
	LineNumberTableEntry[] lntab = getLineNumberTable();
        if (lntab != null) {
            for (int i = 0; i < lntab.length; i++) {
                LineNumberTableEntry e = lntab[i];
                e.startPC = newOffsets[indexByPC[e.startPC]];
            }
        }

        // Update the line number table
	LocalVariableTableEntry[] locvartab = getLocalVariableTable();
        if (locvartab != null) {
            for (int i = 0; i < locvartab.length; i++) {
                LocalVariableTableEntry e = locvartab[i];
                e.pc0 = newOffsets[indexByPC[e.pc0]];
            }
        }

	// Update the stack maps
	if (stackMapTable != null) {
	    for (int i = 0; i < stackMapTable.length; i++) {
		StackMapFrame frame = stackMapTable[i];
		frame.offset = newOffsets[indexByPC[frame.offset]];
	    }
	}
        // make the changes permanent
	code = newCode;
    
public voidrelocateConstantReferences(ConstantObject[] table)

	if ( code == null ) return; // no code, no relocation
	if ( ldcInstructions != null ){
	    int list[] = ldcInstructions;
	    int n = list.length;
	    for (int i = 0; i < n; i++){
		int j = list[i]+1;
		if ( j <= 0 ) continue;
		ConstantObject c = table[ (int)code[j]&0xff ];
		if ( c.shared )
		    throw new DataFormatException("code reference to shared constant");
		int v = c.index;
		if ( v < 0 )
		    throw new DataFormatException("code reference to deleted constant at "+qualifiedName()+"+"+Integer.toHexString(j));
		if ( v > 255 )
		    throw new DataFormatException("ldc subscript out of range at "+qualifiedName()+"+"+Integer.toHexString(j));
		code[j] = (byte)v;
	    }
	}
	if ( wideConstantRefInstructions != null ){
	    int list[] = wideConstantRefInstructions;
	    int n = list.length;
	    for (int i = 0; i < n; i++){
		int j = list[i]+1;
		if ( j <= 0 ) continue;
		ConstantObject c = table[ getUnsignedShort(j) ];
		if ( c.shared )
		    throw new DataFormatException("code reference to shared constant at "+qualifiedName()+"+"+Integer.toHexString(j));
		int v = c.index;
		if ( v < 0 )
		    throw new DataFormatException("code reference to deleted constant at "+qualifiedName()+"+"+Integer.toHexString(j));
		putShort( j, (short)v );
	    }
	}
    
public voidreplaceCode(int start, int end)

 
	replaceCode(start, end, new byte[0]);
    
public voidreplaceCode(int start, int end, int op1)

 
	byte code[] = { (byte)op1 };
	replaceCode(start, end, code);
    
public voidreplaceCode(int start, int end, int op1, int op2)

 
	byte code[] = { (byte)op1, (byte)op2 };
	replaceCode(start, end, code);
    
public voidreplaceCode(int start, int end, int op1, int op2, int op3)

 
	byte code[] = { (byte)op1, (byte)op2, (byte)op3 };
	replaceCode(start, end, code);
    
public voidreplaceCode(int start, int end, byte[] replaceCode)

 
        if (end - start < replaceCode.length) { 
	    // System.out.println("  Cannot yet do expansion!!");
	    return;
	}
        if (exceptionTable != null && exceptionTable.length > 0) {   
	    for (int i = 0; i < exceptionTable.length; i++) { 
	       int startPC = exceptionTable[i].startPC;
	       int endPC = exceptionTable[i].endPC;
	       if (startPC >= start && startPC < end) 
		   return;
	       if (endPC >= start && endPC < end) 
		   return;
	    }
	}
	int startExtra = start + replaceCode.length;
	int extra = end - startExtra;
	
	System.arraycopy(replaceCode, 0, code, start, replaceCode.length);

	for (int i = startExtra; i < end; i++) 
	    code[i] = (byte)opc_nop;
    
private static final intshortAt(byte[] codeBytes, int index)
Return the short stored at a given index from the offset within code bytes

    	return ((codeBytes[index] & 0xFF) << 8) 
    	    | (codeBytes[index+1] & 0xFF);
    
public booleanthrowsExceptions()

	return exceptionsThrown != null;
    
public java.lang.StringtoString()

	String r = "Method: "+super.toString();
	if ( code != null ){
	    r += " {"+code.length+" bytes of code}";
	}
	return r;
    
public voidwrite(java.io.DataOutput o)

	o.writeShort( access );
	o.writeShort( name.index );
	o.writeShort( type.index );
	Attribute.writeAttributes( methodAttributes, o, false );