private static String lookupSwitch(CodeIterator iter, int pos) {
    StringBuffer buffer = new StringBuffer("lookupswitch {\n");
    int index = (pos & ~3) + 4;
    // default
    buffer.append("\t\tdefault: ").append(pos + iter.s32bitAt(index)).append("\n");
    int npairs = iter.s32bitAt(index += 4);
    int end = npairs * 8 + (index += 4);

    for (; index < end; index += 8) {
      int match = iter.s32bitAt(index);
      int target = iter.s32bitAt(index + 4) + pos;
      buffer.append("\t\t").append(match).append(": ").append(target).append("\n");
    }

    buffer.setCharAt(buffer.length() - 1, '}');
    return buffer.toString();
  }
  private static String tableSwitch(CodeIterator iter, int pos) {
    StringBuffer buffer = new StringBuffer("tableswitch {\n");
    int index = (pos & ~3) + 4;
    // default
    buffer.append("\t\tdefault: ").append(pos + iter.s32bitAt(index)).append("\n");
    int low = iter.s32bitAt(index += 4);
    int high = iter.s32bitAt(index += 4);
    int end = (high - low + 1) * 4 + (index += 4);

    // Offset table
    for (int key = low; index < end; index += 4, key++) {
      int target = iter.s32bitAt(index) + pos;
      buffer.append("\t\t").append(key).append(": ").append(target).append("\n");
    }

    buffer.setCharAt(buffer.length() - 1, '}');
    return buffer.toString();
  }
  /** Gets a string representation of the bytecode instruction at the specified position. */
  public static String instructionString(CodeIterator iter, int pos, ConstPool pool) {
    int opcode = iter.byteAt(pos);

    if (opcode > opcodes.length || opcode < 0)
      throw new IllegalArgumentException("Invalid opcode, opcode: " + opcode + " pos: " + pos);

    String opstring = opcodes[opcode];
    switch (opcode) {
      case BIPUSH:
        return opstring + " " + iter.byteAt(pos + 1);
      case SIPUSH:
        return opstring + " " + iter.s16bitAt(pos + 1);
      case LDC:
        return opstring + " " + ldc(pool, iter.byteAt(pos + 1));
      case LDC_W:
      case LDC2_W:
        return opstring + " " + ldc(pool, iter.u16bitAt(pos + 1));
      case ILOAD:
      case LLOAD:
      case FLOAD:
      case DLOAD:
      case ALOAD:
      case ISTORE:
      case LSTORE:
      case FSTORE:
      case DSTORE:
      case ASTORE:
        return opstring + " " + iter.byteAt(pos + 1);
      case IFEQ:
      case IFGE:
      case IFGT:
      case IFLE:
      case IFLT:
      case IFNE:
      case IFNONNULL:
      case IFNULL:
      case IF_ACMPEQ:
      case IF_ACMPNE:
      case IF_ICMPEQ:
      case IF_ICMPGE:
      case IF_ICMPGT:
      case IF_ICMPLE:
      case IF_ICMPLT:
      case IF_ICMPNE:
        return opstring + " " + (iter.s16bitAt(pos + 1) + pos);
      case IINC:
        return opstring + " " + iter.byteAt(pos + 1);
      case GOTO:
      case JSR:
        return opstring + " " + (iter.s16bitAt(pos + 1) + pos);
      case RET:
        return opstring + " " + iter.byteAt(pos + 1);
      case TABLESWITCH:
        return tableSwitch(iter, pos);
      case LOOKUPSWITCH:
        return lookupSwitch(iter, pos);
      case GETSTATIC:
      case PUTSTATIC:
      case GETFIELD:
      case PUTFIELD:
        return opstring + " " + fieldInfo(pool, iter.u16bitAt(pos + 1));
      case INVOKEVIRTUAL:
      case INVOKESPECIAL:
      case INVOKESTATIC:
        return opstring + " " + methodInfo(pool, iter.u16bitAt(pos + 1));
      case INVOKEINTERFACE:
        return opstring + " " + interfaceMethodInfo(pool, iter.u16bitAt(pos + 1));
      case INVOKEDYNAMIC:
        return opstring + " " + iter.u16bitAt(pos + 1);
      case NEW:
        return opstring + " " + classInfo(pool, iter.u16bitAt(pos + 1));
      case NEWARRAY:
        return opstring + " " + arrayInfo(iter.byteAt(pos + 1));
      case ANEWARRAY:
      case CHECKCAST:
        return opstring + " " + classInfo(pool, iter.u16bitAt(pos + 1));
      case WIDE:
        return wide(iter, pos);
      case MULTIANEWARRAY:
        return opstring + " " + classInfo(pool, iter.u16bitAt(pos + 1));
      case GOTO_W:
      case JSR_W:
        return opstring + " " + (iter.s32bitAt(pos + 1) + pos);
      default:
        return opstring;
    }
  }