Better error handling for GenerateMainDexList
Unwrap ExecutionException, and report all errors on the provided
DiagnosticsHandler same way as the D8, R8 and DexSplitter.
Bug: 112679440
Change-Id: I6b803f0e6585c1461eeacfcac1845b363508ef69
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 475d34f..76e7277 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -201,8 +201,7 @@
.write(executor);
options.printWarnings();
} catch (ExecutionException e) {
- R8.unwrapExecutionException(e);
- throw new AssertionError(e); // unwrapping method should have thrown
+ throw R8.unwrapExecutionException(e);
} finally {
options.signalFinishedToConsumers();
// Dump timings.
diff --git a/src/main/java/com/android/tools/r8/DexFileMergerHelper.java b/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
index a26924e..d7183c8 100644
--- a/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
+++ b/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
@@ -105,8 +105,7 @@
writer.write(executor);
options.printWarnings();
} catch (ExecutionException e) {
- R8.unwrapExecutionException(e);
- throw new AssertionError(e); // unwrapping method should have thrown
+ throw R8.unwrapExecutionException(e);
} finally {
options.signalFinishedToConsumers();
}
diff --git a/src/main/java/com/android/tools/r8/DexSplitterHelper.java b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
index 68dc702..163c46f 100644
--- a/src/main/java/com/android/tools/r8/DexSplitterHelper.java
+++ b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
@@ -109,8 +109,7 @@
}
}
} catch (ExecutionException e) {
- R8.unwrapExecutionException(e);
- throw new AssertionError(e); // unwrapping method should have thrown
+ throw R8.unwrapExecutionException(e);
} catch (FeatureMappingException e) {
options.reporter.error(e.getMessage());
} finally {
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
index fe946da..43989ff 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
import com.android.tools.r8.shaking.TreePruner;
import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
@@ -36,37 +37,41 @@
}
private List<String> run(AndroidApp app, ExecutorService executor)
- throws IOException, ExecutionException {
- DexApplication application =
- new ApplicationReader(app, options, timing).read(executor).toDirect();
- AppInfoWithSubtyping appInfo = new AppInfoWithSubtyping(application);
- RootSet mainDexRootSet =
- new RootSetBuilder(appInfo, application, options.mainDexKeepRules, options).run(executor);
- Enqueuer enqueuer = new Enqueuer(appInfo, GraphLense.getIdentityLense(), options, true);
- AppInfoWithLiveness mainDexAppInfo = enqueuer.traceMainDex(mainDexRootSet, executor, timing);
- // LiveTypes is the result.
- Set<DexType> mainDexClasses =
- new MainDexListBuilder(new HashSet<>(mainDexAppInfo.liveTypes), application).run();
+ throws IOException {
+ try {
+ DexApplication application =
+ new ApplicationReader(app, options, timing).read(executor).toDirect();
+ AppInfoWithSubtyping appInfo = new AppInfoWithSubtyping(application);
+ RootSet mainDexRootSet =
+ new RootSetBuilder(appInfo, application, options.mainDexKeepRules, options).run(executor);
+ Enqueuer enqueuer = new Enqueuer(appInfo, GraphLense.getIdentityLense(), options, true);
+ AppInfoWithLiveness mainDexAppInfo = enqueuer.traceMainDex(mainDexRootSet, executor, timing);
+ // LiveTypes is the result.
+ Set<DexType> mainDexClasses =
+ new MainDexListBuilder(new HashSet<>(mainDexAppInfo.liveTypes), application).run();
- List<String> result = mainDexClasses.stream()
- .map(c -> c.toSourceString().replace('.', '/') + ".class")
- .sorted()
- .collect(Collectors.toList());
+ List<String> result = mainDexClasses.stream()
+ .map(c -> c.toSourceString().replace('.', '/') + ".class")
+ .sorted()
+ .collect(Collectors.toList());
- if (options.mainDexListConsumer != null) {
- options.mainDexListConsumer.accept(String.join("\n", result), options.reporter);
+ if (options.mainDexListConsumer != null) {
+ options.mainDexListConsumer.accept(String.join("\n", result), options.reporter);
+ }
+
+ // Print -whyareyoukeeping results if any.
+ if (mainDexRootSet.reasonAsked.size() > 0) {
+ // Print reasons on the application after pruning, so that we reflect the actual result.
+ TreePruner pruner = new TreePruner(application, mainDexAppInfo.withLiveness(), options);
+ application = pruner.run();
+ ReasonPrinter reasonPrinter = enqueuer.getReasonPrinter(mainDexRootSet.reasonAsked);
+ reasonPrinter.run(application);
+ }
+
+ return result;
+ } catch (ExecutionException e) {
+ throw R8.unwrapExecutionException(e);
}
-
- // Print -whyareyoukeeping results if any.
- if (mainDexRootSet.reasonAsked.size() > 0) {
- // Print reasons on the application after pruning, so that we reflect the actual result.
- TreePruner pruner = new TreePruner(application, mainDexAppInfo.withLiveness(), options);
- application = pruner.run();
- ReasonPrinter reasonPrinter = enqueuer.getReasonPrinter(mainDexRootSet.reasonAsked);
- reasonPrinter.run(application);
- }
-
- return result;
}
/**
@@ -82,7 +87,7 @@
* @return classes to keep in the primary dex file.
*/
public static List<String> run(GenerateMainDexListCommand command)
- throws IOException, ExecutionException {
+ throws CompilationFailedException {
ExecutorService executorService = ThreadUtils.getExecutorService(command.getInternalOptions());
try {
return run(command, executorService);
@@ -105,14 +110,28 @@
* @return classes to keep in the primary dex file.
*/
public static List<String> run(GenerateMainDexListCommand command, ExecutorService executor)
- throws IOException, ExecutionException {
+ throws CompilationFailedException {
AndroidApp app = command.getInputApp();
InternalOptions options = command.getInternalOptions();
- return new GenerateMainDexList(options).run(app, executor);
+ ResultBox result = new ResultBox();
+
+ ExceptionUtils.withMainDexListHandler(
+ command.getReporter(),
+ () -> {
+ try {
+ result.content = new GenerateMainDexList(options).run(app, executor);
+ } finally {
+ executor.shutdown();
+ }
+ });
+ return result.content;
}
- public static void main(String[] args)
- throws IOException, ExecutionException, CompilationFailedException {
+ private static class ResultBox {
+ List<String> content;
+ }
+
+ public static void main(String[] args) throws CompilationFailedException {
GenerateMainDexListCommand.Builder builder = GenerateMainDexListCommand.parse(args);
GenerateMainDexListCommand command = builder.build();
if (command.isPrintHelp()) {
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java b/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
index f9e0ebf..2d06da8 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
@@ -150,6 +150,10 @@
return mainDexListConsumer;
}
+ Reporter getReporter() {
+ return reporter;
+ }
+
private static void parse(String[] args, GenerateMainDexListCommand.Builder builder) {
for (int i = 0; i < args.length; i++) {
String arg = args[i].trim();
diff --git a/src/main/java/com/android/tools/r8/PrintSeeds.java b/src/main/java/com/android/tools/r8/PrintSeeds.java
index 4410d8a..78cb75a 100644
--- a/src/main/java/com/android/tools/r8/PrintSeeds.java
+++ b/src/main/java/com/android/tools/r8/PrintSeeds.java
@@ -92,8 +92,7 @@
System.out,
type -> descriptors.contains(type.toDescriptorString()));
} catch (ExecutionException e) {
- R8.unwrapExecutionException(e);
- throw new AssertionError(e); // unwrapping method should have thrown
+ throw R8.unwrapExecutionException(e);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 9738c8d..1bfe039 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -525,8 +525,7 @@
options.printWarnings();
} catch (ExecutionException e) {
- unwrapExecutionException(e);
- throw new AssertionError(e); // unwrapping method should have thrown
+ throw unwrapExecutionException(e);
} finally {
options.signalFinishedToConsumers();
// Dump timings.
@@ -545,7 +544,7 @@
}
}
- static void unwrapExecutionException(ExecutionException executionException) {
+ static RuntimeException unwrapExecutionException(ExecutionException executionException) {
Throwable cause = executionException.getCause();
if (cause instanceof CompilationError) {
// add original exception as suppressed exception to provide the original stack trace
diff --git a/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java b/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
index fe8adfa..1ff2664 100644
--- a/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
@@ -48,6 +48,11 @@
withCompilationHandler(reporter, action);
}
+ public static void withMainDexListHandler(
+ Reporter reporter, CompileAction action) throws CompilationFailedException {
+ withCompilationHandler(reporter, action);
+ }
+
public static void withCompilationHandler(Reporter reporter, CompileAction action)
throws CompilationFailedException {
try {