public static CatchTable build(RopMethod method, int[] order, BlockAddresses addresses) {
    int len = order.length;
    BasicBlockList blocks = method.getBlocks();
    ArrayList<CatchTable.Entry> resultList = new ArrayList<CatchTable.Entry>(len);
    CatchHandlerList currentHandlers = CatchHandlerList.EMPTY;
    BasicBlock currentStartBlock = null;
    BasicBlock currentEndBlock = null;

    for (int i = 0; i < len; i++) {
      BasicBlock block = blocks.labelToBlock(order[i]);

      if (!block.canThrow()) {
        /*
         * There is no need to concern ourselves with the
         * placement of blocks that can't throw with respect
         * to the blocks that *can* throw.
         */
        continue;
      }

      CatchHandlerList handlers = handlersFor(block, addresses);

      if (currentHandlers.size() == 0) {
        // This is the start of a new catch range.
        currentStartBlock = block;
        currentEndBlock = block;
        currentHandlers = handlers;
        continue;
      }

      if (currentHandlers.equals(handlers) && rangeIsValid(currentStartBlock, block, addresses)) {
        /*
         * The block we are looking at now has the same handlers
         * as the block that started the currently open catch
         * range, and adding it to the currently open range won't
         * cause it to be too long.
         */
        currentEndBlock = block;
        continue;
      }

      /*
       * The block we are looking at now has incompatible handlers,
       * so we need to finish off the last entry and start a new
       * one. Note: We only emit an entry if it has associated handlers.
       */
      if (currentHandlers.size() != 0) {
        CatchTable.Entry entry =
            makeEntry(currentStartBlock, currentEndBlock, currentHandlers, addresses);
        resultList.add(entry);
      }

      currentStartBlock = block;
      currentEndBlock = block;
      currentHandlers = handlers;
    }

    if (currentHandlers.size() != 0) {
      // Emit an entry for the range that was left hanging.
      CatchTable.Entry entry =
          makeEntry(currentStartBlock, currentEndBlock, currentHandlers, addresses);
      resultList.add(entry);
    }

    // Construct the final result.

    int resultSz = resultList.size();

    if (resultSz == 0) {
      return CatchTable.EMPTY;
    }

    CatchTable result = new CatchTable(resultSz);

    for (int i = 0; i < resultSz; i++) {
      result.set(i, resultList.get(i));
    }

    result.setImmutable();
    return result;
  }
Builds and returns the catch table for a given method.

@param method {@code non-null;} method to build the list for
@param order {@code non-null;} block output order
@param addresses {@code non-null;} address objects for each block
@return {@code non-null;} the constructed table
android/android_framework/dex-maker/src/main/java/com/android/dx/dex/code/StdCatchBuilder.java