private int parseNewarray(int offset, Visitor visitor) {
    int value = bytes.getUnsignedByte(offset + 1);
    CstType type;
    switch (value) {
      case ByteOps.NEWARRAY_BOOLEAN:
        {
          type = CstType.BOOLEAN_ARRAY;
          break;
        }
      case ByteOps.NEWARRAY_CHAR:
        {
          type = CstType.CHAR_ARRAY;
          break;
        }
      case ByteOps.NEWARRAY_DOUBLE:
        {
          type = CstType.DOUBLE_ARRAY;
          break;
        }
      case ByteOps.NEWARRAY_FLOAT:
        {
          type = CstType.FLOAT_ARRAY;
          break;
        }
      case ByteOps.NEWARRAY_BYTE:
        {
          type = CstType.BYTE_ARRAY;
          break;
        }
      case ByteOps.NEWARRAY_SHORT:
        {
          type = CstType.SHORT_ARRAY;
          break;
        }
      case ByteOps.NEWARRAY_INT:
        {
          type = CstType.INT_ARRAY;
          break;
        }
      case ByteOps.NEWARRAY_LONG:
        {
          type = CstType.LONG_ARRAY;
          break;
        }
      default:
        {
          throw new SimException("bad newarray code " + Hex.u1(value));
        }
    }

    // Revisit the previous bytecode to find out the length of the array
    int previousOffset = visitor.getPreviousOffset();
    ConstantParserVisitor constantVisitor = new ConstantParserVisitor();
    int arrayLength = 0;

    /*
     * For visitors that don't record the previous offset, -1 will be
     * seen here
     */
    if (previousOffset >= 0) {
      parseInstruction(previousOffset, constantVisitor);
      if (constantVisitor.cst instanceof CstInteger
          && constantVisitor.length + previousOffset == offset) {
        arrayLength = constantVisitor.value;
      }
    }

    /*
     * Try to match the array initialization idiom. For example, if the
     * subsequent code is initializing an int array, we are expecting the
     * following pattern repeatedly:
     *  dup
     *  push index
     *  push value
     *  *astore
     *
     * where the index value will be incrimented sequentially from 0 up.
     */
    int nInit = 0;
    int curOffset = offset + 2;
    int lastOffset = curOffset;
    ArrayList<Constant> initVals = new ArrayList<Constant>();

    if (arrayLength != 0) {
      while (true) {
        boolean punt = false;

        // First, check if the next bytecode is dup.
        int nextByte = bytes.getUnsignedByte(curOffset++);
        if (nextByte != ByteOps.DUP) break;

        /*
         * Next, check if the expected array index is pushed to
         * the stack.
         */
        parseInstruction(curOffset, constantVisitor);
        if (constantVisitor.length == 0
            || !(constantVisitor.cst instanceof CstInteger)
            || constantVisitor.value != nInit) break;

        // Next, fetch the init value and record it.
        curOffset += constantVisitor.length;

        /*
         * Next, find out what kind of constant is pushed onto
         * the stack.
         */
        parseInstruction(curOffset, constantVisitor);
        if (constantVisitor.length == 0 || !(constantVisitor.cst instanceof CstLiteralBits)) break;

        curOffset += constantVisitor.length;
        initVals.add(constantVisitor.cst);

        nextByte = bytes.getUnsignedByte(curOffset++);
        // Now, check if the value is stored to the array properly.
        switch (value) {
          case ByteOps.NEWARRAY_BYTE:
          case ByteOps.NEWARRAY_BOOLEAN:
            {
              if (nextByte != ByteOps.BASTORE) {
                punt = true;
              }
              break;
            }
          case ByteOps.NEWARRAY_CHAR:
            {
              if (nextByte != ByteOps.CASTORE) {
                punt = true;
              }
              break;
            }
          case ByteOps.NEWARRAY_DOUBLE:
            {
              if (nextByte != ByteOps.DASTORE) {
                punt = true;
              }
              break;
            }
          case ByteOps.NEWARRAY_FLOAT:
            {
              if (nextByte != ByteOps.FASTORE) {
                punt = true;
              }
              break;
            }
          case ByteOps.NEWARRAY_SHORT:
            {
              if (nextByte != ByteOps.SASTORE) {
                punt = true;
              }
              break;
            }
          case ByteOps.NEWARRAY_INT:
            {
              if (nextByte != ByteOps.IASTORE) {
                punt = true;
              }
              break;
            }
          case ByteOps.NEWARRAY_LONG:
            {
              if (nextByte != ByteOps.LASTORE) {
                punt = true;
              }
              break;
            }
          default:
            punt = true;
            break;
        }
        if (punt) {
          break;
        }
        lastOffset = curOffset;
        nInit++;
      }
    }

    /*
     * For singleton arrays it is still more economical to
     * generate the aput.
     */
    if (nInit < 2 || nInit != arrayLength) {
      visitor.visitNewarray(offset, 2, type, null);
      return 2;
    } else {
      visitor.visitNewarray(offset, lastOffset - offset, type, initVals);
      return lastOffset - offset;
    }
  }
Helper to deal with {@code newarray}.

@param offset the offset to the {@code newarray} opcode itself
@param visitor {@code non-null;} visitor to use
@return instruction length, in bytes
android/android_framework/dex-maker/src/main/java/com/android/dx/cf/code/BytecodeArray.java