private int runMultiDex() throws IOException {

    assert !args.incremental;

    if (args.mainDexListFile != null) {
      classesInMainDex = new HashSet<String>();
      readPathsFromFile(args.mainDexListFile, classesInMainDex);
    }

    dexOutPool = Executors.newFixedThreadPool(args.numThreads);

    if (!processAllFiles()) {
      return 1;
    }

    if (!libraryDexBuffers.isEmpty()) {
      throw new DexException("Library dex files are not supported in multi-dex mode");
    }

    if (outputDex != null) {
      // this array is null if no classes were defined

      dexOutputFutures.add(dexOutPool.submit(new DexWriter(outputDex)));

      // Effectively free up the (often massive) DexFile memory.
      outputDex = null;
    }
    try {
      dexOutPool.shutdown();
      if (!dexOutPool.awaitTermination(600L, TimeUnit.SECONDS)) {
        throw new RuntimeException("Timed out waiting for dex writer threads.");
      }

      for (Future<byte[]> f : dexOutputFutures) {
        dexOutputArrays.add(f.get());
      }

    } catch (InterruptedException ex) {
      dexOutPool.shutdownNow();
      throw new RuntimeException("A dex writer thread has been interrupted.");
    } catch (Exception e) {
      dexOutPool.shutdownNow();
      throw new RuntimeException("Unexpected exception in dex writer thread");
    }

    if (args.jarOutput) {
      for (int i = 0; i < dexOutputArrays.size(); i++) {
        outputResources.put(getDexFileName(i), dexOutputArrays.get(i));
      }

      if (!createJar(args.outName)) {
        return 3;
      }
    } else if (args.outName != null) {
      File outDir = new File(args.outName);
      assert outDir.isDirectory();
      for (int i = 0; i < dexOutputArrays.size(); i++) {
        OutputStream out = new FileOutputStream(new File(outDir, getDexFileName(i)));
        try {
          out.write(dexOutputArrays.get(i));
        } finally {
          closeOutput(out);
        }
      }
    }

    return 0;
  }
Returns the "fixed" version of a given file path, suitable for use as a path within a {@code
.jar} file and for checking against a classfile-internal "this class" name. This looks for the
last instance of the substring {@code "/./"} within the path, and if it finds it, it takes the
portion after to be the fixed path. If that isn't found but the path starts with {@code "./"},
then that prefix is removed and the rest is return. If neither of these is the case, this
method returns its argument.

@param path {@code non-null;} the path to "fix"
@return {@code non-null;} the fixed version (which might be the same as the given {@code path})
android/android_framework/dex-maker/src/main/java/com/android/dx/command/dexer/Main.java