Merge "Tests for field minification in presence of reserved names"
diff --git a/build.gradle b/build.gradle
index 1a7de42..3385270 100644
--- a/build.gradle
+++ b/build.gradle
@@ -37,7 +37,7 @@
     guavaVersion = '23.0'
     joptSimpleVersion = '4.6'
     gsonVersion = '2.7'
-    junitVersion = '4.12'
+    junitVersion = '4.13-beta-2'
     mockitoVersion = '2.10.0'
     kotlinVersion = '1.3.11'
     kotlinExtMetadataJVMVersion = '0.0.4'
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg
index 80de746..dd2e88a 100644
--- a/infra/config/global/luci-scheduler.cfg
+++ b/infra/config/global/luci-scheduler.cfg
@@ -152,7 +152,7 @@
   id: "linux"
   acl_sets: "default"
   triggering_policy: {
-    max_concurrent_invocations: 2
+    max_concurrent_invocations: 3
   }
   buildbucket {
     server: "cr-buildbucket.appspot.com"
@@ -165,7 +165,7 @@
   id: "linux-android-4.0.4"
   acl_sets: "default"
   triggering_policy: {
-    max_concurrent_invocations: 2
+    max_concurrent_invocations: 3
   }
   buildbucket {
     server: "cr-buildbucket.appspot.com"
@@ -187,6 +187,9 @@
 job {
   id: "linux-android-4.4.4"
   acl_sets: "default"
+  triggering_policy: {
+    max_concurrent_invocations: 2
+  }
   buildbucket {
     server: "cr-buildbucket.appspot.com"
     bucket: "luci.r8.ci"
@@ -207,6 +210,9 @@
 job {
   id: "linux-android-5.1.1"
   acl_sets: "default"
+  triggering_policy: {
+    max_concurrent_invocations: 2
+  }
   buildbucket {
     server: "cr-buildbucket.appspot.com"
     bucket: "luci.r8.ci"
@@ -227,6 +233,9 @@
 job {
   id: "linux-android-6.0.1"
   acl_sets: "default"
+  triggering_policy: {
+    max_concurrent_invocations: 3
+  }
   buildbucket {
     server: "cr-buildbucket.appspot.com"
     bucket: "luci.r8.ci"
@@ -247,6 +256,9 @@
 job {
   id: "linux-android-7.0.0"
   acl_sets: "default"
+  triggering_policy: {
+    max_concurrent_invocations: 2
+  }
   buildbucket {
     server: "cr-buildbucket.appspot.com"
     bucket: "luci.r8.ci"
diff --git a/src/main/java/com/android/tools/r8/code/Instruction.java b/src/main/java/com/android/tools/r8/code/Instruction.java
index c451db2..d7e67d4 100644
--- a/src/main/java/com/android/tools/r8/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/code/Instruction.java
@@ -19,9 +19,10 @@
 import java.util.function.BiPredicate;
 
 public abstract class Instruction {
+  public static final Instruction[] EMPTY_ARRAY = {};
 
   public final static int[] NO_TARGETS = null;
-  public final static int[] EXIT_TARGET = new int[]{};
+  public final static int[] EXIT_TARGET = {};
 
   public int offset;
 
diff --git a/src/main/java/com/android/tools/r8/code/InstructionFactory.java b/src/main/java/com/android/tools/r8/code/InstructionFactory.java
index 83b0570..6b60f29 100644
--- a/src/main/java/com/android/tools/r8/code/InstructionFactory.java
+++ b/src/main/java/com/android/tools/r8/code/InstructionFactory.java
@@ -26,7 +26,7 @@
       Instruction instruction = readFrom(range, mapping);
       insn.add(instruction);
     }
-    return insn.toArray(new Instruction[insn.size()]);
+    return insn.toArray(Instruction.EMPTY_ARRAY);
   }
 
   private static class ShortBufferBytecodeStream implements BytecodeStream {
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index d4fb8e3..ac91a4f 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -443,7 +443,7 @@
         DexAnnotation[] copy =
             ObjectArrays.concat(
                 clazz.annotations.annotations,
-                annotations.toArray(new DexAnnotation[annotations.size()]),
+                annotations.toArray(DexAnnotation.EMPTY_ARRAY),
                 DexAnnotation.class);
         clazz.annotations = new DexAnnotationSet(copy);
       }
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index 9f28bfc..28044b5 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -530,7 +530,7 @@
         }
       }
     }
-    return new DexDebugInfo(start, parameters, events.toArray(new DexDebugEvent[events.size()]));
+    return new DexDebugInfo(start, parameters, events.toArray(DexDebugEvent.EMPTY_ARRAY));
   }
 
   private static class MemberAnnotationIterator<S extends Descriptor<?, S>, T extends DexItem> {
@@ -1131,7 +1131,7 @@
         int size = lazyAnnotations.size();
         return size == 0
             ? DexAnnotationSet.empty()
-            : new DexAnnotationSet(lazyAnnotations.toArray(new DexAnnotation[size]));
+            : new DexAnnotationSet(lazyAnnotations.toArray(DexAnnotation.EMPTY_ARRAY));
       }
       return originalAnnotations;
     }
diff --git a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
index b2a3e09..2936d80 100644
--- a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
+++ b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
@@ -126,7 +126,7 @@
             oldCode.registerSize,
             oldCode.incomingRegisterSize,
             oldCode.outgoingRegisterSize,
-            newInstructions.toArray(new Instruction[newInstructions.size()]),
+            newInstructions.toArray(Instruction.EMPTY_ARRAY),
             newTries,
             newHandlers,
             newDebugInfo);
@@ -245,7 +245,7 @@
       return new DexDebugInfo(
           code.getDebugInfo().startLine,
           code.getDebugInfo().parameters,
-          events.toArray(new DexDebugEvent[events.size()]));
+          events.toArray(DexDebugEvent.EMPTY_ARRAY));
     }
     return code.getDebugInfo();
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
index 1168c45..6fc1e1d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
@@ -22,6 +22,7 @@
 import java.util.function.Function;
 
 public class DexAnnotation extends DexItem {
+  public static final DexAnnotation[] EMPTY_ARRAY = {};
   public static final int VISIBILITY_BUILD = 0x00;
   public static final int VISIBILITY_RUNTIME = 0x01;
   public static final int VISIBILITY_SYSTEM = 0x02;
@@ -198,7 +199,7 @@
     return createSystemValueAnnotation(factory.annotationDefault, factory,
         new DexValueAnnotation(
             new DexEncodedAnnotation(type,
-                defaults.toArray(new DexAnnotationElement[defaults.size()])))
+                defaults.toArray(DexAnnotationElement.EMPTY_ARRAY)))
     );
   }
 
@@ -306,7 +307,7 @@
       at = endAt;
     }
 
-    return new DexValueArray(parts.toArray(new DexValue[parts.size()]));
+    return new DexValueArray(parts.toArray(DexValue.EMPTY_ARRAY));
   }
 
   private static DexValue toDexValue(String string, DexItemFactory factory) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java
index 040d256..10c6535 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.dex.MixedSectionCollection;
 
 public class DexAnnotationElement extends DexItem {
+  public static final DexAnnotationElement[] EMPTY_ARRAY = {};
 
   public final DexString name;
   public final DexValue value;
diff --git a/src/main/java/com/android/tools/r8/graph/DexByteCodeWriter.java b/src/main/java/com/android/tools/r8/graph/DexByteCodeWriter.java
index 60893c7..9710fe8 100644
--- a/src/main/java/com/android/tools/r8/graph/DexByteCodeWriter.java
+++ b/src/main/java/com/android/tools/r8/graph/DexByteCodeWriter.java
@@ -66,7 +66,7 @@
       if (anyMethodMatches(clazz)) {
         PrintStream ps = outputStreamProvider.apply(clazz);
         try {
-          writeClass(clazz, outputStreamProvider.apply(clazz));
+          writeClass(clazz, ps);
         } finally {
           closer.accept(ps);
         }
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 8f9a0b6..82678c7 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -23,6 +23,7 @@
 import java.util.function.Predicate;
 
 public abstract class DexClass extends DexDefinition {
+  public static final DexClass[] EMPTY_ARRAY = {};
 
   public interface FieldSetter {
     void setField(int index, DexEncodedField field);
@@ -32,8 +33,6 @@
     void setMethod(int index, DexEncodedMethod method);
   }
 
-  private static final DexEncodedMethod[] NO_METHODS = {};
-  private static final DexEncodedField[] NO_FIELDS = {};
   private Optional<DexEncodedMethod> cachedClassInitializer = null;
 
   public final Origin origin;
@@ -44,16 +43,16 @@
   public DexString sourceFile;
 
   /** Access has to be synchronized during concurrent collection/writing phase. */
-  protected DexEncodedField[] staticFields = NO_FIELDS;
+  protected DexEncodedField[] staticFields = DexEncodedField.EMPTY_ARRAY;
 
   /** Access has to be synchronized during concurrent collection/writing phase. */
-  protected DexEncodedField[] instanceFields = NO_FIELDS;
+  protected DexEncodedField[] instanceFields = DexEncodedField.EMPTY_ARRAY;
 
   /** Access has to be synchronized during concurrent collection/writing phase. */
-  protected DexEncodedMethod[] directMethods = NO_METHODS;
+  protected DexEncodedMethod[] directMethods = DexEncodedMethod.EMPTY_ARRAY;
 
   /** Access has to be synchronized during concurrent collection/writing phase. */
-  protected DexEncodedMethod[] virtualMethods = NO_METHODS;
+  protected DexEncodedMethod[] virtualMethods = DexEncodedMethod.EMPTY_ARRAY;
 
   /** Enclosing context of this class if it is an inner class, null otherwise. */
   private EnclosingMethodAttribute enclosingMethod;
@@ -182,7 +181,7 @@
 
   public void setDirectMethods(DexEncodedMethod[] methods) {
     cachedClassInitializer = null;
-    directMethods = MoreObjects.firstNonNull(methods, NO_METHODS);
+    directMethods = MoreObjects.firstNonNull(methods, DexEncodedMethod.EMPTY_ARRAY);
     assert verifyCorrectnessOfMethodHolders(directMethods());
     assert verifyNoDuplicateMethods();
   }
@@ -232,7 +231,7 @@
   }
 
   public void setVirtualMethods(DexEncodedMethod[] methods) {
-    virtualMethods = MoreObjects.firstNonNull(methods, NO_METHODS);
+    virtualMethods = MoreObjects.firstNonNull(methods, DexEncodedMethod.EMPTY_ARRAY);
     assert verifyCorrectnessOfMethodHolders(virtualMethods());
     assert verifyNoDuplicateMethods();
   }
@@ -394,7 +393,7 @@
   }
 
   public void setStaticFields(DexEncodedField[] fields) {
-    staticFields = MoreObjects.firstNonNull(fields, NO_FIELDS);
+    staticFields = MoreObjects.firstNonNull(fields, DexEncodedField.EMPTY_ARRAY);
     assert verifyCorrectnessOfFieldHolders(staticFields());
     assert verifyNoDuplicateFields();
   }
@@ -453,7 +452,7 @@
   }
 
   public void setInstanceFields(DexEncodedField[] fields) {
-    instanceFields = MoreObjects.firstNonNull(fields, NO_FIELDS);
+    instanceFields = MoreObjects.firstNonNull(fields, DexEncodedField.EMPTY_ARRAY);
     assert verifyCorrectnessOfFieldHolders(instanceFields());
     assert verifyNoDuplicateFields();
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
index 779678d..f790131 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
@@ -11,6 +11,7 @@
 import java.util.Objects;
 
 abstract public class DexDebugEvent extends DexItem {
+  public static final DexDebugEvent[] EMPTY_ARRAY = {};
 
   @Override
   public void collectIndexedItems(IndexedItemCollection collection,
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
index 6be948b..53d2835 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
@@ -118,7 +118,7 @@
         params[i] = (local == null || local.signature != null) ? null : local.name;
       }
     }
-    return new DexDebugInfo(startLine, params, events.toArray(new DexDebugEvent[events.size()]));
+    return new DexDebugInfo(startLine, params, events.toArray(DexDebugEvent.EMPTY_ARRAY));
   }
 
   private void updateBlockEntry(Instruction instruction) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index ec1506a..3a1dfc5 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -11,8 +11,7 @@
 import com.android.tools.r8.utils.InternalOptions;
 
 public class DexEncodedField extends KeyedDexItem<DexField> {
-
-  public static final DexEncodedField[] EMPTY_ARRAY = new DexEncodedField[]{};
+  public static final DexEncodedField[] EMPTY_ARRAY = {};
 
   public final DexField field;
   public final FieldAccessFlags accessFlags;
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 9546590..3d3ed81 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -91,7 +91,7 @@
     PROCESSED_INLINING_CANDIDATE_SAME_CLASS,
   }
 
-  public static final DexEncodedMethod[] EMPTY_ARRAY = new DexEncodedMethod[]{};
+  public static final DexEncodedMethod[] EMPTY_ARRAY = {};
   public static final DexEncodedMethod SENTINEL =
       new DexEncodedMethod(null, null, null, null, null);
 
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 5ef8072..243557c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -39,6 +39,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
@@ -686,6 +687,7 @@
     public final DexMethod appendObject;
     public final DexMethod appendString;
     public final DexMethod appendStringBuffer;
+    private final Set<DexMethod> appenders;
 
     private StringBuildingMethods(DexType receiver) {
       DexType sbufType = createType(createString("Ljava/lang/StringBuffer;"));
@@ -706,23 +708,29 @@
       appendObject = createMethod(receiver, createProto(receiver, objectType), append);
       appendString = createMethod(receiver, createProto(receiver, stringType), append);
       appendStringBuffer = createMethod(receiver, createProto(receiver, sbufType), append);
+
+      appenders = new HashSet<>();
+      appenders.add(appendBoolean);
+      appenders.add(appendChar);
+      appenders.add(appendCharArray);
+      appenders.add(appendSubCharArray);
+      appenders.add(appendCharSequence);
+      appenders.add(appendSubCharSequence);
+      appenders.add(appendInt);
+      appenders.add(appendDouble);
+      appenders.add(appendFloat);
+      appenders.add(appendLong);
+      appenders.add(appendObject);
+      appenders.add(appendString);
+      appenders.add(appendStringBuffer);
+    }
+
+    public boolean isAppend(DexMethod method) {
+      return appenders.contains(method);
     }
 
     public void forEachAppendMethod(Consumer<DexMethod> consumer) {
-      consumer.accept(appendBoolean);
-      consumer.accept(appendChar);
-      consumer.accept(appendCharArray);
-      consumer.accept(appendSubCharArray);
-      consumer.accept(appendCharSequence);
-      consumer.accept(appendSubCharSequence);
-      consumer.accept(appendInt);
-      consumer.accept(appendDouble);
-      consumer.accept(appendFloat);
-      consumer.accept(appendLong);
-      consumer.accept(appendObject);
-      consumer.accept(appendString);
-      consumer.accept(appendStringBuffer);
-      consumer.accept(appendBoolean);
+      appenders.forEach(consumer);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 4312bfd..20f4b19 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -19,9 +19,10 @@
 import java.util.function.Supplier;
 
 public class DexProgramClass extends DexClass implements Supplier<DexProgramClass> {
+  public static final DexProgramClass[] EMPTY_ARRAY = {};
 
   private static final DexEncodedArray SENTINEL_NOT_YET_COMPUTED =
-      new DexEncodedArray(new DexValue[0]);
+      new DexEncodedArray(DexValue.EMPTY_ARRAY);
 
   private final ProgramResource.Kind originKind;
   private DexEncodedArray staticValues = SENTINEL_NOT_YET_COMPUTED;
@@ -282,12 +283,10 @@
             length = i + 1;
           }
         }
-        if (length > 0) {
-          staticValues = new DexEncodedArray(
-              values.subList(0, length).toArray(new DexValue[length]));
-        } else {
-          staticValues = null;
-        }
+        staticValues =
+            length > 0
+                ? new DexEncodedArray(values.subList(0, length).toArray(DexValue.EMPTY_ARRAY))
+                : null;
       }
     }
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 83ab503..f41f466 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -30,14 +30,14 @@
 import java.util.function.Predicate;
 
 public class DexType extends DexReference implements PresortedComparable<DexType> {
-
-  private final static int ROOT_LEVEL = 0;
-  private final static int UNKNOWN_LEVEL = -1;
-  private final static int INTERFACE_LEVEL = -2;
+  public static final DexType[] EMPTY_ARRAY = {};
+  private static final int ROOT_LEVEL = 0;
+  private static final int UNKNOWN_LEVEL = -1;
+  private static final int INTERFACE_LEVEL = -2;
 
   // Since most Java types has no sub-types, we can just share an empty immutable set until we need
   // to add to it.
-  private final static Set<DexType> NO_DIRECT_SUBTYPE = ImmutableSet.of();
+  private static final Set<DexType> NO_DIRECT_SUBTYPE = ImmutableSet.of();
 
   public final DexString descriptor;
   private String toStringCache = null;
diff --git a/src/main/java/com/android/tools/r8/graph/DexTypeList.java b/src/main/java/com/android/tools/r8/graph/DexTypeList.java
index 45a1548..a124bc4 100644
--- a/src/main/java/com/android/tools/r8/graph/DexTypeList.java
+++ b/src/main/java/com/android/tools/r8/graph/DexTypeList.java
@@ -20,7 +20,7 @@
   }
 
   private DexTypeList() {
-    this.values = new DexType[0];
+    this.values = DexType.EMPTY_ARRAY;
   }
 
   public DexTypeList(DexType[] values) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexValue.java b/src/main/java/com/android/tools/r8/graph/DexValue.java
index c582d0f..4f12fda 100644
--- a/src/main/java/com/android/tools/r8/graph/DexValue.java
+++ b/src/main/java/com/android/tools/r8/graph/DexValue.java
@@ -22,6 +22,7 @@
 import org.objectweb.asm.Type;
 
 public abstract class DexValue extends DexItem {
+  public static final DexValue[] EMPTY_ARRAY = {};
 
   public static final UnknownDexValue UNKNOWN = UnknownDexValue.UNKNOWN;
 
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index 3170b63..e788222 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -335,10 +335,10 @@
               enclosingMember,
               innerClasses,
               createAnnotationSet(annotations),
-              staticFields.toArray(new DexEncodedField[staticFields.size()]),
-              instanceFields.toArray(new DexEncodedField[instanceFields.size()]),
-              directMethods.toArray(new DexEncodedMethod[directMethods.size()]),
-              virtualMethods.toArray(new DexEncodedMethod[virtualMethods.size()]),
+              staticFields.toArray(DexEncodedField.EMPTY_ARRAY),
+              instanceFields.toArray(DexEncodedField.EMPTY_ARRAY),
+              directMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
+              virtualMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
               application.getFactory().getSkipNameValidationForTesting());
       if (clazz.isProgramClass()) {
         context.owner = clazz.asProgramClass();
@@ -416,7 +416,7 @@
   private static DexAnnotationSet createAnnotationSet(List<DexAnnotation> annotations) {
     return annotations == null || annotations.isEmpty()
         ? DexAnnotationSet.empty()
-        : new DexAnnotationSet(annotations.toArray(new DexAnnotation[annotations.size()]));
+        : new DexAnnotationSet(annotations.toArray(DexAnnotation.EMPTY_ARRAY));
   }
 
   private static class CreateFieldVisitor extends FieldVisitor {
@@ -673,8 +673,8 @@
               method, parent.origin, parameterCount, parameterNames.size());
         }
         getAnnotations().add(DexAnnotation.createMethodParametersAnnotation(
-            parameterNames.toArray(new DexValue[parameterNames.size()]),
-            parameterFlags.toArray(new DexValue[parameterFlags.size()]),
+            parameterNames.toArray(DexValue.EMPTY_ARRAY),
+            parameterFlags.toArray(DexValue.EMPTY_ARRAY),
             parent.application.getFactory()));
       }
       DexEncodedMethod dexMethod =
@@ -765,7 +765,7 @@
     public AnnotationVisitor visitArray(String name) {
       return new CreateAnnotationVisitor(application, (names, values) -> {
         assert names == null;
-        addElement(name, new DexValueArray(values.toArray(new DexValue[values.size()])));
+        addElement(name, new DexValueArray(values.toArray(DexValue.EMPTY_ARRAY)));
       });
     }
 
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java b/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
index 5cbdf26..a29ae60 100644
--- a/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
+++ b/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
@@ -134,8 +134,8 @@
     }
   }
 
-  private static DexProgramClass[] sortClasses(DexApplication application,
-      Collection<DexProgramClass> classes) {
+  private static DexProgramClass[] sortClasses(
+      DexApplication application, Collection<DexProgramClass> classes) {
     // Collect classes in subtyping order, based on a sorted list of classes to start with.
     ProgramClassDepthsMemoized classDepths = new ProgramClassDepthsMemoized(application);
     List<DexProgramClass> sortedClasses =
@@ -148,7 +148,7 @@
                   return dx != dy ? dx - dy : x.type.compareTo(y.type);
                 })
             .collect(Collectors.toList());
-    return sortedClasses.toArray(new DexProgramClass[sortedClasses.size()]);
+    return sortedClasses.toArray(DexProgramClass.EMPTY_ARRAY);
   }
 
   private static <T> Collection<T> keysOrEmpty(Map<T, ?> map) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
index f8465d0..1668959 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
@@ -154,7 +154,7 @@
       InternalOptions options,
       Timing timing) {
     CallGraph graph = new CallGraph(options);
-    DexClass[] classes = application.classes().toArray(new DexClass[application.classes().size()]);
+    DexClass[] classes = application.classes().toArray(DexClass.EMPTY_ARRAY);
     Arrays.sort(classes, (DexClass a, DexClass b) -> a.type.slowCompareTo(b.type));
     for (DexClass clazz : classes) {
       for (DexEncodedMethod method : clazz.allMethodsSorted()) {
@@ -304,7 +304,7 @@
 
       // Sort the callees before calling traverse recursively. This will ensure cycles are broken
       // the same way across multiple invocations of the R8 compiler.
-      Node[] callees = node.callees.toArray(new Node[node.callees.size()]);
+      Node[] callees = node.callees.toArray(new Node[]{});
       Arrays.sort(callees, (Node a, Node b) -> a.method.method.slowCompareTo(b.method.method));
       if (options.testing.nondeterministicCycleElimination) {
         reorderNodes(Arrays.asList(callees));
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
index 6fbe1e2..f295ddd 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
@@ -266,7 +266,7 @@
             registerAllocator.registersUsed(),
             inRegisterCount,
             outRegisterCount,
-            dexInstructions.toArray(new Instruction[dexInstructions.size()]),
+            dexInstructions.toArray(Instruction.EMPTY_ARRAY),
             tryInfo.tries,
             tryInfo.handlers,
             debugEventBuilder.build());
@@ -809,7 +809,7 @@
           pairs.add(new TypeAddrPair(type, targetOffset));
         }
       }
-      TypeAddrPair[] pairsArray = pairs.toArray(new TypeAddrPair[pairs.size()]);
+      TypeAddrPair[] pairsArray = pairs.toArray(new TypeAddrPair[]{});
       handlers[j] = new TryHandler(pairsArray, catchAllOffset);
     }
     return handlers;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index e91f1cc..eabaec5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -111,8 +111,7 @@
 
     // If at least one bridge method was removed then update the table.
     if (remainingMethods.size() < iface.virtualMethods().size()) {
-      iface.setVirtualMethods(remainingMethods.toArray(
-          new DexEncodedMethod[remainingMethods.size()]));
+      iface.setVirtualMethods(remainingMethods.toArray(DexEncodedMethod.EMPTY_ARRAY));
     }
     remainingMethods.clear();
 
@@ -165,8 +164,7 @@
       }
     }
     if (remainingMethods.size() < iface.directMethods().size()) {
-      iface.setDirectMethods(remainingMethods.toArray(
-          new DexEncodedMethod[remainingMethods.size()]));
+      iface.setDirectMethods(remainingMethods.toArray(DexEncodedMethod.EMPTY_ARRAY));
     }
 
     if (companionMethods.isEmpty()) {
@@ -198,7 +196,7 @@
             DexAnnotationSet.empty(),
             DexEncodedField.EMPTY_ARRAY,
             DexEncodedField.EMPTY_ARRAY,
-            companionMethods.toArray(new DexEncodedMethod[companionMethods.size()]),
+            companionMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
             DexEncodedMethod.EMPTY_ARRAY,
             rewriter.factory.getSkipNameValidationForTesting(),
             Collections.singletonList(iface));
@@ -273,7 +271,7 @@
             DexAnnotationSet.empty(),
             DexEncodedField.EMPTY_ARRAY,
             DexEncodedField.EMPTY_ARRAY,
-            dispatchMethods.toArray(new DexEncodedMethod[dispatchMethods.size()]),
+            dispatchMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
             DexEncodedMethod.EMPTY_ARRAY,
             rewriter.factory.getSkipNameValidationForTesting(),
             callers);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 857de34..3dd9322 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -296,8 +296,9 @@
   // Build a list of implemented interfaces.
   private DexTypeList buildInterfaces() {
     List<DexType> interfaces = descriptor.interfaces;
-    return interfaces.isEmpty() ? DexTypeList.empty()
-        : new DexTypeList(interfaces.toArray(new DexType[interfaces.size()]));
+    return interfaces.isEmpty()
+        ? DexTypeList.empty()
+        : new DexTypeList(interfaces.toArray(DexType.EMPTY_ARRAY));
   }
 
   // Creates a delegation target for this particular lambda class. Note that we
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index f5fca72..41c0073 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -566,7 +566,7 @@
 
     DexProto buildProto() {
       if (proto == null) {
-        DexType[] argumentTypesArray = argumentTypes.toArray(new DexType[argumentTypes.size()]);
+        DexType[] argumentTypesArray = argumentTypes.toArray(DexType.EMPTY_ARRAY);
         proto = appView.dexItemFactory().createProto(returnType, argumentTypesArray);
       }
       return proto;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
index 237b044..4226daa 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
@@ -61,9 +61,10 @@
   // Take the attribute from the group, if exists.
   @Override
   protected List<InnerClassAttribute> buildInnerClasses() {
-    return !id.hasInnerClassAttribute() ? Collections.emptyList()
-        : Lists.newArrayList(new InnerClassAttribute(
-            id.innerClassAccess, group.getGroupClassType(), null, null));
+    return !id.hasInnerClassAttribute()
+        ? Collections.emptyList()
+        : Lists.newArrayList(
+            new InnerClassAttribute(id.innerClassAccess, group.getGroupClassType(), null, null));
   }
 
   @Override
@@ -71,9 +72,10 @@
     // Kotlin-style lambdas supported by the merged may only contain optional signature and
     // kotlin metadata annotations. We remove the latter, but keep the signature if present.
     String signature = id.signature;
-    return signature == null ? DexAnnotationSet.empty()
-        : new DexAnnotationSet(new DexAnnotation[]{
-            DexAnnotation.createSignatureAnnotation(signature, factory)});
+    return signature == null
+        ? DexAnnotationSet.empty()
+        : new DexAnnotationSet(
+            new DexAnnotation[]{DexAnnotation.createSignatureAnnotation(signature, factory)});
   }
 
   @Override
@@ -130,7 +132,7 @@
       }
     }
 
-    return result.toArray(new DexEncodedMethod[result.size()]);
+    return result.toArray(DexEncodedMethod.EMPTY_ARRAY);
   }
 
   // Build a map of virtual methods with unique name/proto pointing to a list of methods
@@ -231,7 +233,7 @@
       }
     });
     assert result.isEmpty() == !group.hasAnySingletons();
-    return result.toArray(new DexEncodedField[result.size()]);
+    return result.toArray(DexEncodedField.EMPTY_ARRAY);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNaming.java b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
index e8ea970..a0912d0 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNaming.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
@@ -14,6 +14,7 @@
 import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
 import com.android.tools.r8.position.Position;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
 import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
@@ -214,7 +215,7 @@
     public MethodSignature(String name, String type, Collection<String> parameters) {
       super(name);
       this.type = type;
-      this.parameters = parameters.toArray(new String[parameters.size()]);
+      this.parameters = parameters.toArray(StringUtils.EMPTY_ARRAY);
     }
 
     public static MethodSignature fromDexMethod(DexMethod method) {
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
index a21adfa..81b745c 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.naming.MemberNaming.Signature;
 import com.android.tools.r8.position.TextPosition;
 import com.android.tools.r8.utils.IdentifierUtils;
+import com.android.tools.r8.utils.StringUtils;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.util.HashMap;
@@ -397,7 +398,7 @@
           expect(',');
           items.add(parseType(true));
         }
-        arguments = items.toArray(new String[items.size()]);
+        arguments = items.toArray(StringUtils.EMPTY_ARRAY);
       }
       expect(')');
       signature = new MethodSignature(name, type, arguments);
diff --git a/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java b/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
index f5250d8..500f0d8 100644
--- a/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
@@ -74,7 +74,7 @@
       }
     }
     if (methods != null) {
-      return methods.toArray(new DexEncodedMethod[methods.size()]);
+      return methods.toArray(DexEncodedMethod.EMPTY_ARRAY);
     }
     return null;
   }
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index b8fd5f6..0420876 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -1033,7 +1033,7 @@
       target.interfaces =
           interfaces.isEmpty()
               ? DexTypeList.empty()
-              : new DexTypeList(interfaces.toArray(new DexType[0]));
+              : new DexTypeList(interfaces.toArray(DexType.EMPTY_ARRAY));
       // Step 2: replace fields and methods.
       target.appendDirectMethods(directMethods.values());
       target.appendVirtualMethods(virtualMethods.values());
diff --git a/src/main/java/com/android/tools/r8/utils/FlagFile.java b/src/main/java/com/android/tools/r8/utils/FlagFile.java
index 5f5003f..319580d 100644
--- a/src/main/java/com/android/tools/r8/utils/FlagFile.java
+++ b/src/main/java/com/android/tools/r8/utils/FlagFile.java
@@ -44,6 +44,6 @@
         flags.add(arg);
       }
     }
-    return flags.toArray(new String[flags.size()]);
+    return flags.toArray(StringUtils.EMPTY_ARRAY);
   }
 }
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 277bf8a..ffbe255 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -513,7 +513,7 @@
         new DexDebugInfo(
             positionEventEmitter.getStartLine(),
             debugInfo.parameters,
-            processedEvents.toArray(new DexDebugEvent[processedEvents.size()]));
+            processedEvents.toArray(DexDebugEvent.EMPTY_ARRAY));
 
     // TODO(b/111253214) Remove this as soon as we have external tests testing not only the
     // remapping but whether the non-positional debug events remain intact.
diff --git a/src/main/java/com/android/tools/r8/utils/StringUtils.java b/src/main/java/com/android/tools/r8/utils/StringUtils.java
index c91c288..e5d0227 100644
--- a/src/main/java/com/android/tools/r8/utils/StringUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/StringUtils.java
@@ -13,12 +13,12 @@
 import java.util.function.Function;
 
 public class StringUtils {
+  public static final String[] EMPTY_ARRAY = {};
+  public static final String LINE_SEPARATOR = System.getProperty("line.separator");
 
-  public final static String LINE_SEPARATOR = System.getProperty("line.separator");
-
-  private final static char[] IDENTIFIER_LETTERS
+  private static final char[] IDENTIFIER_LETTERS
       = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_".toCharArray();
-  private final static int NUMBER_OF_LETTERS = IDENTIFIER_LETTERS.length;
+  private static final int NUMBER_OF_LETTERS = IDENTIFIER_LETTERS.length;
 
   public enum BraceType {
     PARENS,
diff --git a/src/test/examplesAndroidO/stringconcat/TestGenerator.java b/src/test/examplesAndroidO/stringconcat/TestGenerator.java
index e72f438..12e5004 100644
--- a/src/test/examplesAndroidO/stringconcat/TestGenerator.java
+++ b/src/test/examplesAndroidO/stringconcat/TestGenerator.java
@@ -89,9 +89,11 @@
                     recentConstants.set(0,
                         ((String) recentConstants.get(0)).substring(RECIPE_PREFIX.length()));
 
-                    mv.visitInvokeDynamicInsn(MAKE_CONCAT_WITH_CONSTANTS.getName(),
-                        removeLastParams(desc, recentConstants.size()), MAKE_CONCAT_WITH_CONSTANTS,
-                        recentConstants.toArray(new Object[recentConstants.size()]));
+                    mv.visitInvokeDynamicInsn(
+                        MAKE_CONCAT_WITH_CONSTANTS.getName(),
+                        removeLastParams(desc, recentConstants.size()),
+                        MAKE_CONCAT_WITH_CONSTANTS,
+                        recentConstants.toArray());
                     recentConstants.clear();
                     return;
                   }
diff --git a/src/test/java/com/android/tools/r8/DXTestBuilder.java b/src/test/java/com/android/tools/r8/DXTestBuilder.java
index 39782ed..e9e7f9c 100644
--- a/src/test/java/com/android/tools/r8/DXTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/DXTestBuilder.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.StringUtils;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.util.ArrayList;
@@ -50,7 +51,7 @@
       List<String> args = new ArrayList<>();
       args.add("--output=" + outJar.toString());
       args.addAll(injars.stream().map(Path::toString).collect(Collectors.toList()));
-      ProcessResult result = ToolHelper.runDX(args.toArray(new String[0]));
+      ProcessResult result = ToolHelper.runDX(args.toArray(StringUtils.EMPTY_ARRAY));
       if (result.exitCode != 0) {
         throw new CompilationFailedException(result.toString());
       }
diff --git a/src/test/java/com/android/tools/r8/R8CFRunExamplesJava9Test.java b/src/test/java/com/android/tools/r8/R8CFRunExamplesJava9Test.java
index c710ed2..de47d8a 100644
--- a/src/test/java/com/android/tools/r8/R8CFRunExamplesJava9Test.java
+++ b/src/test/java/com/android/tools/r8/R8CFRunExamplesJava9Test.java
@@ -9,6 +9,7 @@
 
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
@@ -112,7 +113,11 @@
       thrown.expect(Throwable.class);
     }
     String[] mainAndArgs =
-        ImmutableList.builder().add(qualifiedMainClass).addAll(args).build().toArray(new String[0]);
+        ImmutableList.builder()
+            .add(qualifiedMainClass)
+            .addAll(args)
+            .build()
+            .toArray(StringUtils.EMPTY_ARRAY);
     ProcessResult outputResult = ToolHelper.runJava(Arrays.asList(outputJars), mainAndArgs);
     ToolHelper.ProcessResult inputResult =
         ToolHelper.runJava(ImmutableList.copyOf(inputJars), mainAndArgs);
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index 8b2eaf5..13cc8cb 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -2062,7 +2062,7 @@
       if (specification.skipTest) {
         continue;
       }
-      CompilationOptions thisOptions = new CompilationOptions(vmSpec.spec);
+      CompilationOptions thisOptions = new CompilationOptions(specification);
       if (r8CompilationOptions == null) {
         r8CompilationOptions = thisOptions;
         executeCompilerUnderTest(
diff --git a/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java
index d103efc..daab81d 100644
--- a/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.OffOrAuto;
+import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.TestDescriptionWatcher;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
@@ -621,7 +622,8 @@
         ArrayList<String> javaArgs = Lists.newArrayList(args);
         javaArgs.add(0, qualifiedMainClass);
         ToolHelper.ProcessResult javaResult =
-            ToolHelper.runJava(ImmutableList.copyOf(jars), javaArgs.toArray(new String[0]));
+            ToolHelper.runJava(
+                ImmutableList.copyOf(jars), javaArgs.toArray(StringUtils.EMPTY_ARRAY));
         assertEquals("JVM run failed", javaResult.exitCode, 0);
         assertTrue(
             "JVM output does not match art output.\n\tjvm: "
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 2d08ac1..8fad46b 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -31,6 +31,7 @@
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.PreloadedClassFileProvider;
+import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.TestDescriptionWatcher;
 import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.ZipUtils;
@@ -447,7 +448,7 @@
 
   /** Create a temporary JAR file containing the specified test classes. */
   protected Path jarTestClasses(List<Class<?>> classes) throws IOException {
-    return jarTestClasses(classes.toArray(new Class<?>[classes.size()]));
+    return jarTestClasses(classes.toArray(new Class<?>[]{}));
   }
 
   /**
@@ -825,7 +826,8 @@
     mainAndArgs.add(main);
     mainAndArgs.addAll(args);
     return ToolHelper.runJava(
-        Collections.singletonList(writeToJar(classes)), mainAndArgs.toArray(new String[0]));
+        Collections.singletonList(writeToJar(classes)),
+        mainAndArgs.toArray(StringUtils.EMPTY_ARRAY));
   }
 
   protected ProcessResult runOnJavaRaw(AndroidApp app, String mainClass, List<String> args)
@@ -835,14 +837,14 @@
     List<String> mainAndArgs = new ArrayList<>();
     mainAndArgs.add(mainClass);
     mainAndArgs.addAll(args);
-    return ToolHelper.runJava(out, mainAndArgs.toArray(new String[0]));
+    return ToolHelper.runJava(out, mainAndArgs.toArray(StringUtils.EMPTY_ARRAY));
   }
 
   protected ProcessResult runOnJavaRawNoVerify(AndroidApp app, String mainClass, List<String> args)
       throws IOException {
     Path out = File.createTempFile("junit", ".zip", temp.getRoot()).toPath();
     app.writeToZip(out, OutputMode.ClassFile);
-    return ToolHelper.runJavaNoVerify(out, mainClass, args.toArray(new String[0]));
+    return ToolHelper.runJavaNoVerify(out, mainClass, args.toArray(StringUtils.EMPTY_ARRAY));
   }
 
   /** Run application on Art or Java with the specified main class. */
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 3853ced..97e0d09 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -10,6 +10,7 @@
 import static org.junit.Assert.fail;
 
 import com.android.tools.r8.DeviceRunner.DeviceRunnerConfigurationException;
+import com.android.tools.r8.TestBase.Backend;
 import com.android.tools.r8.ToolHelper.DexVm.Kind;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.errors.Unreachable;
@@ -585,6 +586,13 @@
     return PROGUARD6_0_1 + ".sh";
   }
 
+  public static Backend[] getBackends() {
+    if (getDexVm() == DexVm.ART_DEFAULT) {
+      return Backend.values();
+    }
+    return new Backend[]{Backend.DEX};
+  }
+
   private static String getRetraceScript() {
     if (isWindows()) {
       return RETRACE + ".bat";
@@ -827,8 +835,7 @@
 
   public static Path getPackageDirectoryForTestPackage(Package pkg) {
     List<String> parts = getNamePartsForTestPackage(pkg);
-    return getClassPathForTests().resolve(
-        Paths.get("", parts.toArray(new String[parts.size() - 1])));
+    return getClassPathForTests().resolve(Paths.get("", parts.toArray(StringUtils.EMPTY_ARRAY)));
   }
 
   public static String getJarEntryForTestPackage(Package pkg) {
@@ -865,8 +872,7 @@
 
   public static Path getClassFileForTestClass(Class clazz) {
     List<String> parts = getNamePartsForTestClass(clazz);
-    return getClassPathForTests().resolve(
-        Paths.get("", parts.toArray(new String[parts.size() - 1])));
+    return getClassPathForTests().resolve(Paths.get("", parts.toArray(StringUtils.EMPTY_ARRAY)));
   }
 
   public static Collection<Path> getClassFilesForInnerClasses(Path path) throws IOException {
@@ -893,7 +899,7 @@
 
   public static Path getFileNameForTestClass(Class clazz) {
     List<String> parts = getNamePartsForTestClass(clazz);
-    return Paths.get("", parts.toArray(new String[parts.size() - 1]));
+    return Paths.get("", parts.toArray(StringUtils.EMPTY_ARRAY));
   }
 
   public static String getJarEntryForTestClass(Class clazz) {
@@ -1065,7 +1071,7 @@
     List<String> args = new ArrayList<>();
     Collections.addAll(args, extraArgs);
     Collections.addAll(args, "--output=" + outDir + "/classes.dex", fileName);
-    int result = runDX(args.toArray(new String[args.size()])).exitCode;
+    int result = runDX(args.toArray(StringUtils.EMPTY_ARRAY)).exitCode;
     return result != 0 ? null : builderFromProgramDirectory(Paths.get(outDir)).build();
   }
 
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/ConstructorRelaxationTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/ConstructorRelaxationTest.java
index 3bdfa7e..beb9235 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/ConstructorRelaxationTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/ConstructorRelaxationTest.java
@@ -9,6 +9,7 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -160,7 +161,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ConstructorRelaxationTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/NoRelaxationForSerializableTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/NoRelaxationForSerializableTest.java
index 8fc4c6f..08b378d 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/NoRelaxationForSerializableTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/NoRelaxationForSerializableTest.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverMerge;
 import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.FileUtils;
@@ -100,7 +101,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}, access-modification: {1}")
   public static List<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   public NoRelaxationForSerializableTest(Backend backend, boolean accessModification) {
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java
index a6e1aa7..e99a3d4 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/NonConstructorRelaxationTest.java
@@ -35,7 +35,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}, argument removal: {1}")
   public static List<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   public NonConstructorRelaxationTest(Backend backend, boolean enableArgumentRemoval) {
diff --git a/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java b/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
index 001c520..ebae273 100644
--- a/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
+++ b/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.R8TestBuilder;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import java.nio.file.Path;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -18,7 +19,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/classmerging/InliningAfterStaticClassMergerTest.java b/src/test/java/com/android/tools/r8/classmerging/InliningAfterStaticClassMergerTest.java
index 4a331a7..2e2a772 100644
--- a/src/test/java/com/android/tools/r8/classmerging/InliningAfterStaticClassMergerTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/InliningAfterStaticClassMergerTest.java
@@ -9,6 +9,7 @@
 import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -63,7 +64,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/classmerging/StaticClassMergerInterfaceTest.java b/src/test/java/com/android/tools/r8/classmerging/StaticClassMergerInterfaceTest.java
index 294eca0..52d195c 100644
--- a/src/test/java/com/android/tools/r8/classmerging/StaticClassMergerInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/StaticClassMergerInterfaceTest.java
@@ -27,7 +27,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public StaticClassMergerInterfaceTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/classmerging/StaticClassMergerTest.java b/src/test/java/com/android/tools/r8/classmerging/StaticClassMergerTest.java
index ff76f08..d3ef317 100644
--- a/src/test/java/com/android/tools/r8/classmerging/StaticClassMergerTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/StaticClassMergerTest.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.AssumeMayHaveSideEffects;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
@@ -56,7 +57,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/classmerging/StaticInitializerTest.java b/src/test/java/com/android/tools/r8/classmerging/StaticInitializerTest.java
index ce89fe1..72c9e57 100644
--- a/src/test/java/com/android/tools/r8/classmerging/StaticInitializerTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/StaticInitializerTest.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -19,7 +20,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public StaticInitializerTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/compatdx/CompatDxTests.java b/src/test/java/com/android/tools/r8/compatdx/CompatDxTests.java
index 7d181bc..4ec0131 100644
--- a/src/test/java/com/android/tools/r8/compatdx/CompatDxTests.java
+++ b/src/test/java/com/android/tools/r8/compatdx/CompatDxTests.java
@@ -125,7 +125,7 @@
     // Only test this with CompatDx, as dx does not like the empty .dex file.
     List<String> d8Args =ImmutableList.of(
         "--output=" + temp.newFolder("out").toString(), jarWithClassesAndDex.toString());
-    CompatDx.main(d8Args.toArray(new String[d8Args.size()]));
+    CompatDx.main(d8Args.toArray(StringUtils.EMPTY_ARRAY));
   }
 
   private void runDexer(String... args) throws IOException {
@@ -164,7 +164,7 @@
     }
     Collections.addAll(d8Args, args);
     System.out.println("running: d8 " + StringUtils.join(d8Args, " "));
-    CompatDx.main(d8Args.toArray(new String[d8Args.size()]));
+    CompatDx.main(d8Args.toArray(StringUtils.EMPTY_ARRAY));
 
     List<String> dxArgs = new ArrayList<>(args.length + 2);
     if (dxOut != null) {
@@ -172,7 +172,7 @@
     }
     Collections.addAll(dxArgs, args);
     System.out.println("running: dx " + StringUtils.join(dxArgs, " "));
-    ProcessResult result = ToolHelper.runDX(dxArgs.toArray(new String[dxArgs.size()]));
+    ProcessResult result = ToolHelper.runDX(dxArgs.toArray(StringUtils.EMPTY_ARRAY));
     assertEquals(result.stderr, 0, result.exitCode);
 
     if (out == null) {
diff --git a/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java b/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java
index 4a7494b..678e2da 100644
--- a/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java
+++ b/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java
@@ -451,7 +451,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ReflectionTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/debug/LoadInvokeLoadOptimizationTestRunner.java b/src/test/java/com/android/tools/r8/debug/LoadInvokeLoadOptimizationTestRunner.java
index f741381..785db86 100644
--- a/src/test/java/com/android/tools/r8/debug/LoadInvokeLoadOptimizationTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debug/LoadInvokeLoadOptimizationTestRunner.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.debug;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.FrameInspector;
 import com.android.tools.r8.utils.DescriptorUtils;
 import java.util.List;
@@ -30,7 +31,7 @@
         parameters()
             .add("CF", temp -> testForJvm(temp).addTestClasspath().debugConfig())
             .add("D8", temp -> testForD8(temp).addProgramClasses(CLASS).debugConfig());
-    for (Backend backend : Backend.values()) {
+    for (Backend backend : ToolHelper.getBackends()) {
       parameters.add(
           "R8/" + backend,
           temp ->
diff --git a/src/test/java/com/android/tools/r8/debuginfo/InliningWithoutPositionsTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/InliningWithoutPositionsTestRunner.java
index 980325e..0588b33 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/InliningWithoutPositionsTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/InliningWithoutPositionsTestRunner.java
@@ -94,7 +94,7 @@
   @Test
   public void testStackTrace() throws Exception {
     // See InliningWithoutPositionsTestSourceDump for the code compiled here.
-    Path testClassDir = temp.newFolder(TEST_PACKAGE.split(".")).toPath();
+    Path testClassDir = temp.newFolder().toPath();
     Path testClassPath = testClassDir.resolve(TEST_CLASS + ".class");
     Path outputPath = temp.newFolder().toPath();
 
diff --git a/src/test/java/com/android/tools/r8/debuginfo/PreamblePositionTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/PreamblePositionTestRunner.java
index 14f9f98..90239e7 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/PreamblePositionTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/PreamblePositionTestRunner.java
@@ -37,8 +37,7 @@
   }
 
   private void testBothBranches(boolean invertConditionals) throws Exception {
-    Path testClassDir = temp.newFolder(TEST_PACKAGE.split(".")).toPath();
-    Path testClassPath = testClassDir.resolve(TEST_CLASS + ".class");
+    Path testClassPath = temp.newFolder().toPath().resolve(TEST_CLASS + ".class");
     Path outputDexPath = temp.newFolder().toPath();
 
     Files.write(testClassPath, PreamblePositionTestSourceDump.dump());
diff --git a/src/test/java/com/android/tools/r8/desugar/BasicTestDependenciesDesugaringTest.java b/src/test/java/com/android/tools/r8/desugar/BasicTestDependenciesDesugaringTest.java
index 8af2f8e..20c7e0e 100644
--- a/src/test/java/com/android/tools/r8/desugar/BasicTestDependenciesDesugaringTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/BasicTestDependenciesDesugaringTest.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.OffOrAuto;
+import com.android.tools.r8.utils.StringUtils;
 import com.google.common.collect.Sets;
 import java.io.File;
 import java.io.IOException;
@@ -37,14 +38,13 @@
     try {
       allLibs =
           Files.readAllLines(Paths.get(ToolHelper.BUILD_DIR, "generated", "supportlibraries.txt"))
-          .toArray(new String[0]);
+          .toArray(StringUtils.EMPTY_ARRAY);
     } catch (IOException e) {
       throw new AssertionError(e);
     }
   }
 
-  private static Set<String> knownIssues = Sets.newHashSet(new String[]{
-  });
+  private static Set<String> knownIssues = Sets.newHashSet(StringUtils.EMPTY_ARRAY);
 
   @Rule
   public ExpectedException thrown = ExpectedException.none();
diff --git a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
index 95e1e76..b46bbbf 100644
--- a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
+++ b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
@@ -97,7 +97,7 @@
     instr.setOffset(offset);
     instructions.add(instr);
     assert instr.getOffset() == lastInstructionOffset;
-    return instructions.toArray(new Instruction[instructions.size()]);
+    return instructions.toArray(Instruction.EMPTY_ARRAY);
   }
 
   private int countJumboStrings(Instruction[] instructions) {
diff --git a/src/test/java/com/android/tools/r8/dexsplitter/DexSplitterTests.java b/src/test/java/com/android/tools/r8/dexsplitter/DexSplitterTests.java
index 784dd8d..f503359 100644
--- a/src/test/java/com/android/tools/r8/dexsplitter/DexSplitterTests.java
+++ b/src/test/java/com/android/tools/r8/dexsplitter/DexSplitterTests.java
@@ -22,6 +22,7 @@
 import com.android.tools.r8.dexsplitter.DexSplitter.Options;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.FeatureClassMapping.FeatureMappingException;
+import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.google.common.collect.ImmutableList;
@@ -302,7 +303,7 @@
         args.add("base_renamed");
       }
 
-      DexSplitter.main(args.toArray(new String[0]));
+      DexSplitter.main(args.toArray(StringUtils.EMPTY_ARRAY));
     }
     String baseOutputName = explicitBase || !renameBase ? "base" : "base_renamed";
     Path base = output.resolve(baseOutputName).resolve("classes.dex");
diff --git a/src/test/java/com/android/tools/r8/graph/MissingClassThrowingTest.java b/src/test/java/com/android/tools/r8/graph/MissingClassThrowingTest.java
new file mode 100644
index 0000000..9848767
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/graph/MissingClassThrowingTest.java
@@ -0,0 +1,86 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.graph;
+
+import static org.hamcrest.core.StringContains.containsString;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MissingClassThrowingTest extends TestBase {
+
+  @NeverMerge
+  public static class MissingException extends Exception {}
+
+  @NeverMerge
+  public static class Program {
+
+    public static final String EXPECTED_OUTPUT = "Hello world!";
+
+    @NeverInline
+    private static char[] compile(String[] args) throws IOException, MissingException {
+      if (args.length > 1) {
+        throw new MissingException();
+      } else if (args.length == 1) {
+        throw new IOException();
+      } else {
+        return EXPECTED_OUTPUT.toCharArray();
+      }
+    }
+
+    @NeverInline
+    public static void main(String[] args) {
+      try {
+        System.out.println(compile(args));
+      } catch (IOException | MissingException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withCfRuntime(CfVm.last()).build();
+  }
+
+  public MissingClassThrowingTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Ignore("b/128885552")
+  @Test
+  public void testSuperTypeOfExceptions()
+      throws ExecutionException, CompilationFailedException, IOException {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Program.class)
+        .noMinification()
+        .noTreeShaking()
+        .enableInliningAnnotations()
+        .enableMergeAnnotations()
+        .debug()
+        .addKeepRules(
+            "-keep class ** { *; }",
+            "-keepattributes *")
+        .compile()
+        .addRunClasspathClasses(MissingException.class)
+        .run(parameters.getRuntime(), Program.class)
+        .assertFailureWithErrorThatMatches(
+            containsString("Missing class: " + MissingException.class.getTypeName()));
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/B116282409.java b/src/test/java/com/android/tools/r8/ir/optimize/B116282409.java
index 6008aab..3af47cc 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/B116282409.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/B116282409.java
@@ -45,7 +45,7 @@
 
   @Parameters(name = "Backend: {0}, vertical class merging: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   public B116282409(Backend backend, boolean enableVerticalClassMerging) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/CatchHandlerRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/CatchHandlerRemovalTest.java
index 07e795c..14fc7af 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/CatchHandlerRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/CatchHandlerRemovalTest.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -17,7 +18,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public CatchHandlerRemovalTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizationTest.java
index bb2fc3a..5c731fc 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizationTest.java
@@ -10,6 +10,7 @@
 
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -94,7 +95,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public IdempotentFunctionCallCanonicalizationTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
index d185654..640a20d 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
@@ -47,7 +47,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public MemberValuePropagationTest(TestBase.Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/NonNullParamTest.java b/src/test/java/com/android/tools/r8/ir/optimize/NonNullParamTest.java
index 44497b5..0c66575 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/NonNullParamTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/NonNullParamTest.java
@@ -9,6 +9,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ir.optimize.nonnull.IntrinsicsDeputy;
 import com.android.tools.r8.ir.optimize.nonnull.NonNullParamAfterInvokeDirect;
 import com.android.tools.r8.ir.optimize.nonnull.NonNullParamAfterInvokeInterface;
@@ -39,7 +40,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public NonNullParamTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
index c9e5f1e..f9192db 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
@@ -51,7 +51,7 @@
   public static Collection<Object[]> data() {
     return buildParameters(
         ImmutableList.of("Inlining"),
-        Backend.values(),
+        ToolHelper.getBackends(),
         BooleanUtils.values(),
         BooleanUtils.values());
   }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/RedundantConstNumberRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/RedundantConstNumberRemovalTest.java
index e2f47cd..ffac704 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/RedundantConstNumberRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/RedundantConstNumberRemovalTest.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.R8TestRunResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
@@ -34,7 +35,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public RedundantConstNumberRemovalTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/SubsumedCatchHandlerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/SubsumedCatchHandlerTest.java
index e31325b..65c1496 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/SubsumedCatchHandlerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/SubsumedCatchHandlerTest.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.ForceInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.cf.code.CfTryCatch;
 import com.android.tools.r8.graph.CfCode;
 import com.android.tools.r8.graph.Code;
@@ -66,7 +67,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/checkcast/CheckCastDebugTestRunner.java b/src/test/java/com/android/tools/r8/ir/optimize/checkcast/CheckCastDebugTestRunner.java
index 0033eb2..52a1f72 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/checkcast/CheckCastDebugTestRunner.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/checkcast/CheckCastDebugTestRunner.java
@@ -41,7 +41,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public CheckCastDebugTestRunner(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/checkcast/CheckCastRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/checkcast/CheckCastRemovalTest.java
index ac3b267..33eed50 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/checkcast/CheckCastRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/checkcast/CheckCastRemovalTest.java
@@ -6,6 +6,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.jasmin.JasminBuilder;
 import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
@@ -29,7 +30,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/checkcast/IllegalAccessErrorTest.java b/src/test/java/com/android/tools/r8/ir/optimize/checkcast/IllegalAccessErrorTest.java
index c575fb0..2687c27 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/checkcast/IllegalAccessErrorTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/checkcast/IllegalAccessErrorTest.java
@@ -25,7 +25,7 @@
 
   @Parameterized.Parameters(name = "backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
 
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/checkcast/NullCheckCastTest.java b/src/test/java/com/android/tools/r8/ir/optimize/checkcast/NullCheckCastTest.java
index ab915f6..d6552a7 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/checkcast/NullCheckCastTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/checkcast/NullCheckCastTest.java
@@ -42,7 +42,7 @@
 
   @Parameterized.Parameters(name = "backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public NullCheckCastTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/BuilderWithInheritanceTest.java b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/BuilderWithInheritanceTest.java
index c3deab3..0c38e45 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/BuilderWithInheritanceTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/BuilderWithInheritanceTest.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverMerge;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -24,7 +25,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public BuilderWithInheritanceTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java
index b69569f..5a033cd 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerTest.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.ir.optimize.classinliner.builders.BuildersTestClass;
 import com.android.tools.r8.ir.optimize.classinliner.builders.ControlFlow;
@@ -67,7 +68,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ClassInlinerTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/DevirtualizerNonNullRewritingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/DevirtualizerNonNullRewritingTest.java
index cef7f1b..12bce34 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/DevirtualizerNonNullRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/DevirtualizerNonNullRewritingTest.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverMerge;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -19,7 +20,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public DevirtualizerNonNullRewritingTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/InvokeInterfaceToInvokeVirtualTest.java b/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/InvokeInterfaceToInvokeVirtualTest.java
index d78628f..171dac4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/InvokeInterfaceToInvokeVirtualTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/InvokeInterfaceToInvokeVirtualTest.java
@@ -35,7 +35,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public InvokeInterfaceToInvokeVirtualTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineSynchronizedTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineSynchronizedTest.java
index 519c273..d45d19e 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineSynchronizedTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineSynchronizedTest.java
@@ -9,6 +9,7 @@
 import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.InternalOptions;
@@ -38,7 +39,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}, ClassInlining: {1}")
   public static Collection data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlinerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlinerTest.java
index 8945415..74b2a56 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlinerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlinerTest.java
@@ -43,7 +43,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public InlinerTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java
index 0194a1a..f931dcd 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/InstanceOfRemovalTest.java
@@ -8,6 +8,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -111,7 +112,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedAnnotationTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedAnnotationTypeTest.java
index 987623a..7f61c30 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedAnnotationTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedAnnotationTypeTest.java
@@ -10,6 +10,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -59,7 +60,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedLibraryTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedLibraryTypeTest.java
index 6da0470..cff27b4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedLibraryTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedLibraryTypeTest.java
@@ -10,6 +10,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -60,7 +61,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedProgramTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedProgramTypeTest.java
index a9568db..df2739a 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedProgramTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/instanceofremoval/UninstantiatedProgramTypeTest.java
@@ -11,6 +11,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -59,7 +60,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetClassTest.java b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetClassTest.java
index df06e95..3aa4d9f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetClassTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetClassTest.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -133,7 +134,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public GetClassTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTestBase.java b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTestBase.java
index 979d911..7d10303 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTestBase.java
@@ -27,7 +27,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} minification: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   GetNameTestBase(Backend backend, boolean enableMinification) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/reflection/InnerClassNameTestRunner.java b/src/test/java/com/android/tools/r8/ir/optimize/reflection/InnerClassNameTestRunner.java
index 167d953..f2c24b2 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/reflection/InnerClassNameTestRunner.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/reflection/InnerClassNameTestRunner.java
@@ -116,7 +116,7 @@
 
   @Parameters(name = "{0} minify:{1} {2}")
   public static Collection<Object[]> parameters() {
-    return buildParameters(Backend.values(), BooleanUtils.values(), TestNamingConfig.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values(), TestNamingConfig.values());
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
index 3f4801d..b5071f4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.code.Instruction;
 import com.android.tools.r8.code.InvokeDirect;
 import com.android.tools.r8.code.InvokeStatic;
@@ -63,7 +64,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ClassStaticizerTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/NestedStringBuilderTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/NestedStringBuilderTest.java
index a73b766..efaec9f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/NestedStringBuilderTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/NestedStringBuilderTest.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.ForceInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
@@ -35,7 +36,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public NestedStringBuilderTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringCanonicalizationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringCanonicalizationTest.java
index cf3f64b..ad540ff 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringCanonicalizationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringCanonicalizationTest.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode;
@@ -131,7 +132,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public StringCanonicalizationTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatenationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatenationTest.java
index 7acb30d..3b67c93 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatenationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringConcatenationTest.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.R8TestRunResult;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -39,7 +40,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringContentCheckTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringContentCheckTest.java
index 5e4e5f1..7a220d5 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringContentCheckTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringContentCheckTest.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -180,7 +181,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public StringContentCheckTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringInMonitorTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringInMonitorTest.java
index 0b049e3..17726e9 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringInMonitorTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringInMonitorTest.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -85,7 +86,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public StringInMonitorTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringIsEmptyTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringIsEmptyTest.java
index 0de9105..ec0fe1b 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringIsEmptyTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringIsEmptyTest.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -65,7 +66,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public StringIsEmptyTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringLengthTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringLengthTest.java
index 2d1d0a5..91de9bc 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringLengthTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringLengthTest.java
@@ -98,7 +98,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public StringLengthTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringToStringTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringToStringTest.java
index 60a7c1f..60b6f43 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringToStringTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringToStringTest.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -64,7 +65,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public StringToStringTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java
index f8f5fa4..10b1063 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringUtils;
@@ -130,7 +131,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public StringValueOfTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InterfaceMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InterfaceMethodTest.java
index b609c1e..6346a37 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InterfaceMethodTest.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverMerge;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -26,7 +27,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public InterfaceMethodTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithNonNullParamCheckTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithNonNullParamCheckTest.java
index d39062d..6298428 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithNonNullParamCheckTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithNonNullParamCheckTest.java
@@ -11,6 +11,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -39,7 +40,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public InvokeMethodWithNonNullParamCheckTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithReceiverOptimizationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithReceiverOptimizationTest.java
index 2a805b14..6d2bf67 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithReceiverOptimizationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InvokeMethodWithReceiverOptimizationTest.java
@@ -12,6 +12,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -37,7 +38,7 @@
 
   @Parameters(name = "Backend: {0}, enable argument removal: {1}")
   public static List<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   public InvokeMethodWithReceiverOptimizationTest(Backend backend, boolean enableArgumentRemoval) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/LambdaInstantiatedTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/LambdaInstantiatedTypeTest.java
index bcde05c..063ebf4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/LambdaInstantiatedTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/LambdaInstantiatedTypeTest.java
@@ -8,6 +8,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -27,7 +28,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public LambdaInstantiatedTypeTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java
index e685ae5..b9e8f15 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/ParameterRewritingTest.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverMerge;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -28,7 +29,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ParameterRewritingTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/VoidReturnTypeRewritingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/VoidReturnTypeRewritingTest.java
index e443368..5afad95 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/VoidReturnTypeRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/VoidReturnTypeRewritingTest.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverMerge;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -26,7 +27,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public VoidReturnTypeRewritingTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsBootstrapTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsBootstrapTest.java
index 3001335..0d3f3cb 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsBootstrapTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsBootstrapTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.ir.optimize.unusedarguments;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -17,7 +18,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public UnusedArgumentsBootstrapTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorCollisionTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorCollisionTest.java
index 3b0603c..1e24b24 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorCollisionTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.ir.optimize.unusedarguments;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -19,7 +20,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] parameters() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public UnusedArgumentsInstanceConstructorCollisionTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
index 20d7bae..0d97f02 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -28,7 +29,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public UnusedArgumentsInstanceConstructorTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/jasmin/Regress65432240.java b/src/test/java/com/android/tools/r8/jasmin/Regress65432240.java
index 458ddbc..e34c8b1 100644
--- a/src/test/java/com/android/tools/r8/jasmin/Regress65432240.java
+++ b/src/test/java/com/android/tools/r8/jasmin/Regress65432240.java
@@ -29,7 +29,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public Regress65432240(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/kotlin/MetadataStripTest.java b/src/test/java/com/android/tools/r8/kotlin/MetadataStripTest.java
index eca25fb..572ae96 100644
--- a/src/test/java/com/android/tools/r8/kotlin/MetadataStripTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/MetadataStripTest.java
@@ -40,7 +40,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} target: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), KotlinTargetVersion.values());
+    return buildParameters(ToolHelper.getBackends(), KotlinTargetVersion.values());
   }
 
   public MetadataStripTest(Backend backend, KotlinTargetVersion targetVersion) {
diff --git a/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java b/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java
index 700e2d4..b58ed1e 100644
--- a/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java
@@ -22,7 +22,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} target: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), KotlinTargetVersion.values());
+    return buildParameters(ToolHelper.getBackends(), KotlinTargetVersion.values());
   }
 
   private void test(String... rules) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinStdlibTest.java b/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinStdlibTest.java
index f796046..904647f 100644
--- a/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinStdlibTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinStdlibTest.java
@@ -22,7 +22,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} target: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), KotlinTargetVersion.values());
+    return buildParameters(ToolHelper.getBackends(), KotlinTargetVersion.values());
   }
 
   private void test(String... rules) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
index 6fbcd9d..dd62cac 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
@@ -396,8 +396,8 @@
       index++;
     }
     // Everything else should be sorted according to name.
-    String[] entriesUnsorted = entryNames.toArray(new String[0]);
-    String[] entriesSorted = entryNames.toArray(new String[0]);
+    String[] entriesUnsorted = entryNames.toArray(StringUtils.EMPTY_ARRAY);
+    String[] entriesSorted = entryNames.toArray(StringUtils.EMPTY_ARRAY);
     Arrays.sort(entriesSorted);
     Assert.assertArrayEquals(entriesUnsorted, entriesSorted);
   }
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/IllegalFieldRebindingTest.java b/src/test/java/com/android/tools/r8/memberrebinding/IllegalFieldRebindingTest.java
index cc35cbd..b822934 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/IllegalFieldRebindingTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/IllegalFieldRebindingTest.java
@@ -9,6 +9,7 @@
 import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.memberrebinding.testclasses.IllegalFieldRebindingTestClasses;
 import com.android.tools.r8.memberrebinding.testclasses.IllegalFieldRebindingTestClasses.B;
 import com.android.tools.r8.utils.StringUtils;
@@ -28,7 +29,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public IllegalFieldRebindingTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/IndirectSuperInterfaceTest.java b/src/test/java/com/android/tools/r8/memberrebinding/IndirectSuperInterfaceTest.java
index 977b925..9993999 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/IndirectSuperInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/IndirectSuperInterfaceTest.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.google.common.collect.ImmutableList;
 import java.util.List;
@@ -132,7 +133,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] setup() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public IndirectSuperInterfaceTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
index 4c54504..6175d7a 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
@@ -332,7 +332,7 @@
   @Parameters(name = "{0}")
   public static Collection<TestConfiguration> data() {
     ImmutableList.Builder<TestConfiguration> builder = ImmutableList.builder();
-    for (Backend backend : Backend.values()) {
+    for (Backend backend : ToolHelper.getBackends()) {
       TestConfiguration.add(
           builder,
           "memberrebinding",
diff --git a/src/test/java/com/android/tools/r8/movestringconstants/MoveStringConstantsTest.java b/src/test/java/com/android/tools/r8/movestringconstants/MoveStringConstantsTest.java
index 967277c..d9b3cd4 100644
--- a/src/test/java/com/android/tools/r8/movestringconstants/MoveStringConstantsTest.java
+++ b/src/test/java/com/android/tools/r8/movestringconstants/MoveStringConstantsTest.java
@@ -36,7 +36,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private void runTest(Consumer<CodeInspector> inspection) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/naming/AdaptResourceFileContentsTest.java b/src/test/java/com/android/tools/r8/naming/AdaptResourceFileContentsTest.java
index 15599ef..93d89cf 100644
--- a/src/test/java/com/android/tools/r8/naming/AdaptResourceFileContentsTest.java
+++ b/src/test/java/com/android/tools/r8/naming/AdaptResourceFileContentsTest.java
@@ -18,6 +18,7 @@
 import com.android.tools.r8.DataResourceProvider.Visitor;
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.shaking.forceproguardcompatibility.ProguardCompatibilityTestBase;
 import com.android.tools.r8.utils.ArchiveResourceProvider;
@@ -52,7 +53,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public AdaptResourceFileContentsTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java b/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java
index 40f4249..8c2dafc 100644
--- a/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java
+++ b/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java
@@ -51,7 +51,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public AdaptResourceFileNamesTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/AvoidRTest.java b/src/test/java/com/android/tools/r8/naming/AvoidRTest.java
index 4633b36..2d48d5c 100644
--- a/src/test/java/com/android/tools/r8/naming/AvoidRTest.java
+++ b/src/test/java/com/android/tools/r8/naming/AvoidRTest.java
@@ -10,6 +10,7 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.R8TestBuilder;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.jasmin.JasminBuilder;
 import com.android.tools.r8.jasmin.JasminTestBase;
 import com.android.tools.r8.utils.FileUtils;
@@ -29,7 +30,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public AvoidRTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/EnumMinification.java b/src/test/java/com/android/tools/r8/naming/EnumMinification.java
index 322a879..2b6ff48 100644
--- a/src/test/java/com/android/tools/r8/naming/EnumMinification.java
+++ b/src/test/java/com/android/tools/r8/naming/EnumMinification.java
@@ -36,7 +36,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public EnumMinification(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/EnumMinificationKotlinTest.java b/src/test/java/com/android/tools/r8/naming/EnumMinificationKotlinTest.java
index bdb3330..cd1520e 100644
--- a/src/test/java/com/android/tools/r8/naming/EnumMinificationKotlinTest.java
+++ b/src/test/java/com/android/tools/r8/naming/EnumMinificationKotlinTest.java
@@ -8,6 +8,7 @@
 import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.KotlinTestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -31,7 +32,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} target: {1} minify: {2}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), KotlinTargetVersion.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), KotlinTargetVersion.values(), BooleanUtils.values());
   }
 
   public EnumMinificationKotlinTest(
diff --git a/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java b/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
index 9aa9a0f..7fa8b54 100644
--- a/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
+++ b/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
@@ -112,7 +112,7 @@
 
     // Duplicate parameters for each backend.
     List<Object[]> parametersWithBackend = new ArrayList<>();
-    for (Backend backend : Backend.values()) {
+    for (Backend backend : ToolHelper.getBackends()) {
       for (Object[] row : parameters) {
         Object[] newRow = new Object[row.length + 1];
         newRow[0] = backend;
diff --git a/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java b/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java
index 410ae0a..342019f 100644
--- a/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java
@@ -68,7 +68,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public MinifierClassSignatureTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/MinifierFieldSignatureTest.java b/src/test/java/com/android/tools/r8/naming/MinifierFieldSignatureTest.java
index 1c4e31b..c19ba39 100644
--- a/src/test/java/com/android/tools/r8/naming/MinifierFieldSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/naming/MinifierFieldSignatureTest.java
@@ -65,7 +65,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public MinifierFieldSignatureTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/MinifierMethodSignatureTest.java b/src/test/java/com/android/tools/r8/naming/MinifierMethodSignatureTest.java
index 3c74a5b..ec33a57 100644
--- a/src/test/java/com/android/tools/r8/naming/MinifierMethodSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/naming/MinifierMethodSignatureTest.java
@@ -68,7 +68,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public MinifierMethodSignatureTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java b/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java
index 2ef1f5e..87a2fb2 100644
--- a/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java
+++ b/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java
@@ -34,7 +34,7 @@
 
   @BeforeClass
   public static void initDebuggeePath() throws Exception {
-    for (Backend backend : Backend.values()) {
+    for (Backend backend : ToolHelper.getBackends()) {
       Path outdir = temp.newFolder().toPath();
       Path outjar = outdir.resolve("r8_compiled.jar");
       Path proguardMapPath = outdir.resolve("proguard.map");
@@ -75,7 +75,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public RenameSourceFileDebugTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/WarnReflectiveAccessTest.java b/src/test/java/com/android/tools/r8/naming/WarnReflectiveAccessTest.java
index 74e6471..3652285 100644
--- a/src/test/java/com/android/tools/r8/naming/WarnReflectiveAccessTest.java
+++ b/src/test/java/com/android/tools/r8/naming/WarnReflectiveAccessTest.java
@@ -70,7 +70,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public WarnReflectiveAccessTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterDevirtualizationTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterDevirtualizationTest.java
index 7ef141e..a13a5f6 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterDevirtualizationTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterDevirtualizationTest.java
@@ -9,6 +9,7 @@
 
 import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Assume;
@@ -81,7 +82,7 @@
 
   @Parameterized.Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ApplyMappingAfterDevirtualizationTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterHorizontalMergingFieldTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterHorizontalMergingFieldTest.java
index c97dbfb..1ccdfdd 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterHorizontalMergingFieldTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterHorizontalMergingFieldTest.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Assume;
@@ -69,7 +70,7 @@
 
   @Parameterized.Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ApplyMappingAfterHorizontalMergingFieldTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterHorizontalMergingMethodTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterHorizontalMergingMethodTest.java
index 360dd90..9e370a7 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterHorizontalMergingMethodTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterHorizontalMergingMethodTest.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.NeverPropagateValue;
 import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Assume;
@@ -76,7 +77,7 @@
 
   @Parameterized.Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ApplyMappingAfterHorizontalMergingMethodTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterVerticalMergingFieldTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterVerticalMergingFieldTest.java
index a097ea2..c982b0a 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterVerticalMergingFieldTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingAfterVerticalMergingFieldTest.java
@@ -9,6 +9,7 @@
 
 import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Assume;
@@ -58,7 +59,7 @@
 
   @Parameterized.Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ApplyMappingAfterVerticalMergingFieldTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/ApplyMappingTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/ApplyMappingTest.java
index 6367281..b5e57b5 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/ApplyMappingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/ApplyMappingTest.java
@@ -58,7 +58,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ApplyMappingTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/InnerEnumValuesTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/InnerEnumValuesTest.java
index 913f68d..493ace2 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/InnerEnumValuesTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/InnerEnumValuesTest.java
@@ -8,6 +8,7 @@
 import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.naming.applymapping.sourcelibrary.Outer.InnerEnum;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.StringUtils;
@@ -34,7 +35,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public InnerEnumValuesTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionAsmTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionAsmTest.java
index 38ceec9..a3d3b71 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionAsmTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionAsmTest.java
@@ -41,7 +41,7 @@
 
   @Parameterized.Parameters(name = "backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public MemberResolutionAsmTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java
index 95c3a84..99fc246 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java
@@ -82,7 +82,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public MemberResolutionTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/arraytypes/ArrayTypesTest.java b/src/test/java/com/android/tools/r8/naming/arraytypes/ArrayTypesTest.java
index 0ddb8b5..5315868 100644
--- a/src/test/java/com/android/tools/r8/naming/arraytypes/ArrayTypesTest.java
+++ b/src/test/java/com/android/tools/r8/naming/arraytypes/ArrayTypesTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.naming.arraytypes;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.StringUtils;
@@ -37,7 +38,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Object[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   @BeforeClass
diff --git a/src/test/java/com/android/tools/r8/naming/b114554345/B114554345.java b/src/test/java/com/android/tools/r8/naming/b114554345/B114554345.java
index 0d2ab3a..6ceff62 100644
--- a/src/test/java/com/android/tools/r8/naming/b114554345/B114554345.java
+++ b/src/test/java/com/android/tools/r8/naming/b114554345/B114554345.java
@@ -21,7 +21,7 @@
 
   @Parameters(name = "backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public B114554345(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/b116840216/ReserveOuterClassNameTest.java b/src/test/java/com/android/tools/r8/naming/b116840216/ReserveOuterClassNameTest.java
index dec65d1..090626f 100644
--- a/src/test/java/com/android/tools/r8/naming/b116840216/ReserveOuterClassNameTest.java
+++ b/src/test/java/com/android/tools/r8/naming/b116840216/ReserveOuterClassNameTest.java
@@ -55,7 +55,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ReserveOuterClassNameTest(Backend backend){
diff --git a/src/test/java/com/android/tools/r8/naming/b123068484/FieldRenamingTest.java b/src/test/java/com/android/tools/r8/naming/b123068484/FieldRenamingTest.java
index 4cedaea..d2e7349 100644
--- a/src/test/java/com/android/tools/r8/naming/b123068484/FieldRenamingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/b123068484/FieldRenamingTest.java
@@ -37,7 +37,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Object[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public FieldRenamingTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java b/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java
index 0971e8c..e24eb44 100644
--- a/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java
+++ b/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java
@@ -10,6 +10,7 @@
 import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.FieldSubject;
@@ -31,7 +32,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} minify: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   public B126592786(Backend backend, boolean minify) {
diff --git a/src/test/java/com/android/tools/r8/naming/overloadaggressively/OverloadAggressivelyTest.java b/src/test/java/com/android/tools/r8/naming/overloadaggressively/OverloadAggressivelyTest.java
index fa76e46..e034df6 100644
--- a/src/test/java/com/android/tools/r8/naming/overloadaggressively/OverloadAggressivelyTest.java
+++ b/src/test/java/com/android/tools/r8/naming/overloadaggressively/OverloadAggressivelyTest.java
@@ -33,7 +33,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public OverloadAggressivelyTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java b/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java
index 7a1dead..f718cb6 100644
--- a/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java
+++ b/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java
@@ -8,6 +8,7 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.jasmin.JasminBuilder;
 import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
@@ -36,7 +37,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ValidNameConflictTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/DesugarLambdaRetraceTest.java b/src/test/java/com/android/tools/r8/naming/retrace/DesugarLambdaRetraceTest.java
index 4c43c7c..143e65e 100644
--- a/src/test/java/com/android/tools/r8/naming/retrace/DesugarLambdaRetraceTest.java
+++ b/src/test/java/com/android/tools/r8/naming/retrace/DesugarLambdaRetraceTest.java
@@ -10,6 +10,7 @@
 import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.naming.retrace.StackTrace.StackTraceLine;
 import com.google.common.collect.ImmutableList;
 import java.util.Collection;
@@ -24,7 +25,7 @@
 
   @Parameters(name = "Backend: {0}, mode: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), CompilationMode.values());
+    return buildParameters(ToolHelper.getBackends(), CompilationMode.values());
   }
 
   public DesugarLambdaRetraceTest(Backend backend, CompilationMode mode) {
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/DesugarStaticInterfaceMethodsRetraceTest.java b/src/test/java/com/android/tools/r8/naming/retrace/DesugarStaticInterfaceMethodsRetraceTest.java
index 8114108..93201b1 100644
--- a/src/test/java/com/android/tools/r8/naming/retrace/DesugarStaticInterfaceMethodsRetraceTest.java
+++ b/src/test/java/com/android/tools/r8/naming/retrace/DesugarStaticInterfaceMethodsRetraceTest.java
@@ -9,6 +9,7 @@
 
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.ToolHelper;
 import com.google.common.collect.ImmutableList;
 import java.util.Collection;
 import org.junit.Test;
@@ -21,7 +22,7 @@
 
   @Parameters(name = "Backend: {0}, mode: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), CompilationMode.values());
+    return buildParameters(ToolHelper.getBackends(), CompilationMode.values());
   }
 
   public DesugarStaticInterfaceMethodsRetraceTest(Backend backend, CompilationMode mode) {
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/InliningRetraceTest.java b/src/test/java/com/android/tools/r8/naming/retrace/InliningRetraceTest.java
index c252426..fc6d143 100644
--- a/src/test/java/com/android/tools/r8/naming/retrace/InliningRetraceTest.java
+++ b/src/test/java/com/android/tools/r8/naming/retrace/InliningRetraceTest.java
@@ -11,6 +11,7 @@
 
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.ForceInline;
+import com.android.tools.r8.ToolHelper;
 import com.google.common.collect.ImmutableList;
 import java.util.Collection;
 import org.junit.Test;
@@ -23,7 +24,7 @@
 
   @Parameters(name = "Backend: {0}, mode: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), CompilationMode.values());
+    return buildParameters(ToolHelper.getBackends(), CompilationMode.values());
   }
 
   public InliningRetraceTest(Backend backend, CompilationMode mode) {
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/VerticalClassMergingRetraceTest.java b/src/test/java/com/android/tools/r8/naming/retrace/VerticalClassMergingRetraceTest.java
index 6ef62be..a188b06 100644
--- a/src/test/java/com/android/tools/r8/naming/retrace/VerticalClassMergingRetraceTest.java
+++ b/src/test/java/com/android/tools/r8/naming/retrace/VerticalClassMergingRetraceTest.java
@@ -10,6 +10,7 @@
 
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.naming.retrace.StackTrace.StackTraceLine;
 import com.google.common.collect.ImmutableList;
 import java.util.Collection;
@@ -26,7 +27,7 @@
 
   @Parameters(name = "Backend: {0}, mode: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), CompilationMode.values());
+    return buildParameters(ToolHelper.getBackends(), CompilationMode.values());
   }
 
   public VerticalClassMergingRetraceTest(Backend backend, CompilationMode mode) {
diff --git a/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java b/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java
index 1b0c79c..3a5ffdd 100644
--- a/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java
+++ b/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java
@@ -38,7 +38,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public NeverReturnsNormallyTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/regress/B76025099.java b/src/test/java/com/android/tools/r8/regress/B76025099.java
index 383810b..337e824 100644
--- a/src/test/java/com/android/tools/r8/regress/B76025099.java
+++ b/src/test/java/com/android/tools/r8/regress/B76025099.java
@@ -43,7 +43,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public B76025099(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/regress/b63935662/Regress63935662.java b/src/test/java/com/android/tools/r8/regress/b63935662/Regress63935662.java
index 40af31f..bc53ac7 100644
--- a/src/test/java/com/android/tools/r8/regress/b63935662/Regress63935662.java
+++ b/src/test/java/com/android/tools/r8/regress/b63935662/Regress63935662.java
@@ -23,7 +23,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public Regress63935662(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java b/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
index 8f4e2b3..47f0b1d 100644
--- a/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
+++ b/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
@@ -28,7 +28,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public Regress69825683Test(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/regress/b71604169/Regress71604169Test.java b/src/test/java/com/android/tools/r8/regress/b71604169/Regress71604169Test.java
index 5554548..dba1c0b 100644
--- a/src/test/java/com/android/tools/r8/regress/b71604169/Regress71604169Test.java
+++ b/src/test/java/com/android/tools/r8/regress/b71604169/Regress71604169Test.java
@@ -23,7 +23,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public Regress71604169Test(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/release/ShareCommonCodeOnDistinctPositionsTestRunner.java b/src/test/java/com/android/tools/r8/release/ShareCommonCodeOnDistinctPositionsTestRunner.java
index d70c724..5bc4e02 100644
--- a/src/test/java/com/android/tools/r8/release/ShareCommonCodeOnDistinctPositionsTestRunner.java
+++ b/src/test/java/com/android/tools/r8/release/ShareCommonCodeOnDistinctPositionsTestRunner.java
@@ -34,7 +34,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] parameters() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/resolution/B77944861.java b/src/test/java/com/android/tools/r8/resolution/B77944861.java
index b6aae78..3b74d05 100644
--- a/src/test/java/com/android/tools/r8/resolution/B77944861.java
+++ b/src/test/java/com/android/tools/r8/resolution/B77944861.java
@@ -40,7 +40,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public B77944861(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTest.java b/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTest.java
index 8d35333..5e93601 100644
--- a/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTest.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -72,7 +73,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Object[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public PublicFieldInnerClassTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/resolution/b123730538/B123730538.java b/src/test/java/com/android/tools/r8/resolution/b123730538/B123730538.java
index 462d514..b5f88cd 100644
--- a/src/test/java/com/android/tools/r8/resolution/b123730538/B123730538.java
+++ b/src/test/java/com/android/tools/r8/resolution/b123730538/B123730538.java
@@ -36,7 +36,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Object[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public B123730538(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/resource/DataResourceTest.java b/src/test/java/com/android/tools/r8/resource/DataResourceTest.java
index 81b8447..653059c 100644
--- a/src/test/java/com/android/tools/r8/resource/DataResourceTest.java
+++ b/src/test/java/com/android/tools/r8/resource/DataResourceTest.java
@@ -33,7 +33,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public DataResourceTest(TestBase.Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java b/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java
index 5b7a11e..4cbaf6c 100644
--- a/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java
+++ b/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java
@@ -51,7 +51,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}, Minify: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   public KeepDirectoriesTest(Backend backend, boolean minify) {
diff --git a/src/test/java/com/android/tools/r8/rewrite/switches/SwitchRewritingJarTest.java b/src/test/java/com/android/tools/r8/rewrite/switches/SwitchRewritingJarTest.java
index 24789b0..7987f96 100644
--- a/src/test/java/com/android/tools/r8/rewrite/switches/SwitchRewritingJarTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/switches/SwitchRewritingJarTest.java
@@ -28,7 +28,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public SwitchRewritingJarTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java b/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java
index c0fbd53..afba8bd 100644
--- a/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java
@@ -25,7 +25,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public RewriteSwitchMapsTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java b/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java
index 8dcdd38..ae66a50 100644
--- a/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java
@@ -10,6 +10,7 @@
 
 import com.android.tools.r8.StringConsumer.FileConsumer;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -28,7 +29,7 @@
 
   @Parameters(name = "backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public AtomicFieldUpdaterTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java b/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java
index c15ff24..6b4c8fd 100644
--- a/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java
@@ -51,7 +51,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} minification: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   public EnclosingMethodTest(Backend backend, boolean enableMinification) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java b/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java
index 75dd2b1..20b2850 100644
--- a/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java
@@ -11,6 +11,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.jasmin.JasminBuilder;
 import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
 import com.android.tools.r8.jasmin.JasminTestBase;
@@ -33,7 +34,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Object[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public FieldReadsJasminTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/InstantiatedLambdaReceiverTest.java b/src/test/java/com/android/tools/r8/shaking/InstantiatedLambdaReceiverTest.java
index 225ddd6..16d9503 100644
--- a/src/test/java/com/android/tools/r8/shaking/InstantiatedLambdaReceiverTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/InstantiatedLambdaReceiverTest.java
@@ -22,7 +22,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public InstantiatedLambdaReceiverTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java b/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java
index 6906b76..032bd05 100644
--- a/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java
@@ -76,7 +76,7 @@
 
   @Parameters(name = "Backend: {0}, mode: {1}, use interface: {2}")
   public static Collection<Object[]> parameters() {
-    return buildParameters(Backend.values(), Mode.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), Mode.values(), BooleanUtils.values());
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/shaking/KeepAttributesTest.java b/src/test/java/com/android/tools/r8/shaking/KeepAttributesTest.java
index 08f1da2..8281015 100644
--- a/src/test/java/com/android/tools/r8/shaking/KeepAttributesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/KeepAttributesTest.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.shaking.forceproguardcompatibility.keepattributes.TestKeepAttributes;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
@@ -28,7 +29,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] parameters() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   private final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java
index 8738b74..51dc435 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java
@@ -50,33 +50,31 @@
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-class A {
-  private static String buildClassName(String className) {
-    return A.class.getPackage().getName() + "." + className;
-  }
-
-  public static void main(String[] args) {
-    try {
-      Class bClass = Class.forName(buildClassName("B"));
-      System.out.println("YES");
-    } catch (ClassNotFoundException e) {
-      System.out.println("NO");
-    }
-  }
-}
-
-class B {
-
-}
-
 @RunWith(Parameterized.class)
 public class LibraryProvidedProguardRulesTest extends TestBase {
 
+  static class A {
+    private static String buildClassName(String className) {
+      return com.android.tools.r8.shaking.A.class.getPackage().getName() + "." + className;
+    }
+
+    public static void main(String[] args) {
+      try {
+        Class bClass = Class.forName(buildClassName("B"));
+        System.out.println("YES");
+      } catch (ClassNotFoundException e) {
+        System.out.println("NO");
+      }
+    }
+  }
+
+  static class B {}
+
   private Backend backend;
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public LibraryProvidedProguardRulesTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
index 4be2aaf..287b736 100644
--- a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
@@ -7,19 +7,19 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
 import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.ByteDataView;
 import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
+import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.ir.optimize.Inliner.Reason;
-import com.android.tools.r8.jasmin.JasminBuilder;
-import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
-import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -28,118 +28,169 @@
 import com.google.common.collect.ImmutableSet;
 import java.nio.file.Path;
 import java.util.Collection;
+import java.util.Objects;
+import java.util.function.Function;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.BeforeParam;
 
 @RunWith(Parameterized.class)
 public class NonVirtualOverrideTest extends TestBase {
 
-  private static Class<?> main = NonVirtualOverrideTestClass.class;
-  private static Class<?> A = NonVirtualOverrideTestClass.A.class;
-  private static Class<?> B = NonVirtualOverrideTestClass.B.class;
-  private static Class<?> C = NonVirtualOverrideTestClass.C.class;
-
-  private final Backend backend;
+  private final TestParameters parameters;
   private final boolean enableClassInlining;
   private final boolean enableVerticalClassMerging;
 
+  static class Dimensions {
+
+    private final Backend backend;
+    private final boolean enableClassInlining;
+    private final boolean enableVerticalClassMerging;
+
+    public Dimensions(
+        Backend backend, boolean enableClassInlining, boolean enableVerticalClassMerging) {
+      this.backend = backend;
+      this.enableClassInlining = enableClassInlining;
+      this.enableVerticalClassMerging = enableVerticalClassMerging;
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(backend, enableClassInlining, enableVerticalClassMerging);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (!(o instanceof Dimensions)) {
+        return false;
+      }
+      Dimensions other = (Dimensions) o;
+      return this.backend == other.backend
+          && this.enableClassInlining == other.enableClassInlining
+          && this.enableVerticalClassMerging == other.enableVerticalClassMerging;
+    }
+  }
+
   @Parameterized.Parameters(name = "Backend: {0}, class inlining: {1}, vertical class merging: {2}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values(), BooleanUtils.values());
+    return buildParameters(
+        getTestParameters().withAllRuntimes().build(),
+        BooleanUtils.values(),
+        BooleanUtils.values());
   }
 
   public NonVirtualOverrideTest(
-      Backend backend, boolean enableClassInlining, boolean enableVerticalClassMerging) {
-    this.backend = backend;
+      TestParameters parameters, boolean enableClassInlining, boolean enableVerticalClassMerging) {
+    this.parameters = parameters;
     this.enableClassInlining = enableClassInlining;
     this.enableVerticalClassMerging = enableVerticalClassMerging;
   }
 
-  @Test
-  public void test() throws Exception {
-    // Construct B such that it inherits from A and shadows method A.m() with a private method.
-    JasminBuilder jasminBuilder = new JasminBuilder();
-    ClassBuilder classBuilder = jasminBuilder.addClass(B.getName(), A.getName());
-    classBuilder.addDefaultConstructor();
-    for (String methodName : ImmutableList.of("m1", "m2")) {
-      classBuilder.addPrivateVirtualMethod(
-          methodName, ImmutableList.of(), "V", jasminCodeForPrinting("In B." + methodName + "()"));
-    }
-    for (String methodName : ImmutableList.of("m3", "m4")) {
-      classBuilder.addStaticMethod(
-          methodName, ImmutableList.of(), "V", jasminCodeForPrinting("In B." + methodName + "()"));
-    }
+  @ClassRule public static TemporaryFolder staticTemp = ToolHelper.getTemporaryFolderForTest();
 
-    AndroidApp input =
-        AndroidApp.builder()
-            .addProgramFiles(
-                ToolHelper.getClassFileForTestClass(main),
-                ToolHelper.getClassFileForTestClass(A),
-                ToolHelper.getClassFileForTestClass(C))
-            .addClassProgramData(jasminBuilder.buildClasses())
-            .build();
+  @BeforeParam
+  public static void forceCompilation(
+      TestParameters parameters, boolean enableClassInlining, boolean enableVerticalClassMerging) {
+    expectedResults.apply(isDexVmBetween5_1_1and7_0_0(parameters));
+    compilationResults.apply(
+        new Dimensions(parameters.getBackend(), enableClassInlining, enableVerticalClassMerging));
+  }
 
-    // Run the program using java.
-    String referenceResult;
-    if (backend == Backend.DEX
-        && ToolHelper.getDexVm().getVersion().isOlderThanOrEqual(Version.V7_0_0)
-        && ToolHelper.getDexVm().getVersion().isAtLeast(Version.V5_1_1)) {
-      referenceResult =
-          String.join(
-              System.lineSeparator(),
-              "In A.m1()",
-              "In A.m2()",
-              "In A.m3()",
-              "In A.m4()",
-              "In C.m1()",
-              "In A.m2()",
-              "In C.m3()",
-              "In A.m4()",
-              "In A.m1()", // With Java: Caught IllegalAccessError when calling B.m1()
-              "In A.m3()", // With Java: Caught IncompatibleClassChangeError when calling B.m3()
-              "In C.m1()", // With Java: Caught IllegalAccessError when calling B.m1()
-              "In C.m3()", // With Java: Caught IncompatibleClassChangeError when calling B.m3()
-              "In C.m1()",
-              "In C.m3()",
-              "");
+  private static Function<Boolean, String> expectedResults =
+      memoizeFunction(NonVirtualOverrideTest::getExpectedResult);
+
+  private static Function<Dimensions, R8TestCompileResult> compilationResults =
+      memoizeFunction(NonVirtualOverrideTest::compile);
+
+  public static String getExpectedResult(boolean isOldVm) throws Exception {
+    if (isOldVm) {
+      return String.join(
+          System.lineSeparator(),
+          "In A.m1()",
+          "In A.m2()",
+          "In A.m3()",
+          "In A.m4()",
+          "In C.m1()",
+          "In A.m2()",
+          "In C.m3()",
+          "In A.m4()",
+          "In A.m1()", // With Java: Caught IllegalAccessError when calling B.m1()
+          "In A.m3()", // With Java: Caught IncompatibleClassChangeError when calling B.m3()
+          "In C.m1()", // With Java: Caught IllegalAccessError when calling B.m1()
+          "In C.m3()", // With Java: Caught IncompatibleClassChangeError when calling B.m3()
+          "In C.m1()",
+          "In C.m3()",
+          "");
     } else {
-      Path referenceJar = temp.getRoot().toPath().resolve("input.jar");
+      Path referenceJar = staticTemp.getRoot().toPath().resolve("input.jar");
       ArchiveConsumer inputConsumer = new ArchiveConsumer(referenceJar);
-      for (Class<?> clazz : ImmutableList.of(main, A, C)) {
-        inputConsumer.accept(
-            ByteDataView.of(ToolHelper.getClassAsBytes(clazz)),
-            DescriptorUtils.javaTypeToDescriptor(clazz.getName()),
-            null);
-      }
       inputConsumer.accept(
-          ByteDataView.of(jasminBuilder.buildClasses().get(0)),
-          DescriptorUtils.javaTypeToDescriptor(B.getName()),
+          ByteDataView.of(NonVirtualOverrideTestClassDump.dump()),
+          DescriptorUtils.javaTypeToDescriptor(NonVirtualOverrideTestClass.class.getName()),
+          null);
+      inputConsumer.accept(
+          ByteDataView.of(ADump.dump()),
+          DescriptorUtils.javaTypeToDescriptor(A.class.getName()),
+          null);
+      inputConsumer.accept(
+          ByteDataView.of(BDump.dump()),
+          DescriptorUtils.javaTypeToDescriptor(B.class.getName()),
+          null);
+      inputConsumer.accept(
+          ByteDataView.of(CDump.dump()),
+          DescriptorUtils.javaTypeToDescriptor(C.class.getName()),
           null);
       inputConsumer.finished(null);
 
-      ProcessResult javaResult = ToolHelper.runJava(referenceJar, main.getName());
+      ProcessResult javaResult =
+          ToolHelper.runJava(referenceJar, NonVirtualOverrideTestClass.class.getName());
       assertEquals(javaResult.exitCode, 0);
-      referenceResult = javaResult.stdout;
+      return javaResult.stdout;
     }
+  }
 
-    // Run the program on Art after is has been compiled with R8.
-    AndroidApp compiled =
-        compileWithR8(
-            input,
-            keepMainProguardConfiguration(main),
+  public static boolean isDexVmBetween5_1_1and7_0_0(TestParameters parameters) {
+    if (!parameters.isDexRuntime()) {
+      return false;
+    }
+    Version version = parameters.getRuntime().asDex().getVm().getVersion();
+    return version.isOlderThanOrEqual(Version.V7_0_0) && version.isAtLeast(Version.V5_1_1);
+  }
+
+  public static R8TestCompileResult compile(Dimensions dimensions) throws Exception {
+    return testForR8(staticTemp, dimensions.backend)
+        .addProgramClassFileData(
+            NonVirtualOverrideTestClassDump.dump(), ADump.dump(), BDump.dump(), CDump.dump())
+        .addKeepMainRule(NonVirtualOverrideTestClass.class)
+        .addOptionsModification(
             options -> {
-              options.enableClassInlining = enableClassInlining;
-              options.enableVerticalClassMerging = enableVerticalClassMerging;
+              options.enableClassInlining = dimensions.enableClassInlining;
+              options.enableVerticalClassMerging = dimensions.enableVerticalClassMerging;
               options.testing.validInliningReasons = ImmutableSet.of(Reason.FORCE);
-            },
-            backend);
-    assertEquals(referenceResult, runOnVM(compiled, main, backend));
+            })
+        .setMinApi(AndroidApiLevel.B)
+        .compile();
+  }
+
+  @Test
+  public void test() throws Exception {
+    // Run the program on Art after is has been compiled with R8.
+    String referenceResult = expectedResults.apply(isDexVmBetween5_1_1and7_0_0(parameters));
+    R8TestCompileResult compiled =
+        compilationResults.apply(
+            new Dimensions(
+                parameters.getBackend(), enableClassInlining, enableVerticalClassMerging));
+    compiled
+        .run(parameters.getRuntime(), NonVirtualOverrideTestClass.class)
+        .assertSuccessWithOutput(referenceResult);
 
     // Check that B is present and that it doesn't contain the unused private method m2.
     if (!enableClassInlining && !enableVerticalClassMerging) {
-      CodeInspector inspector = new CodeInspector(compiled);
-      ClassSubject classSubject = inspector.clazz(B.getName());
+      CodeInspector inspector = compiled.inspector();
+      ClassSubject classSubject = inspector.clazz(B.class.getName());
       assertThat(classSubject, isRenamed());
       assertThat(classSubject.method("void", "m1", ImmutableList.of()), isPresent());
       assertThat(classSubject.method("void", "m2", ImmutableList.of()), not(isPresent()));
@@ -147,114 +198,4 @@
       assertThat(classSubject.method("void", "m4", ImmutableList.of()), not(isPresent()));
     }
   }
-
-  private static String[] jasminCodeForPrinting(String message) {
-    return new String[] {
-      ".limit stack 2",
-      ".limit locals 1",
-      "getstatic java/lang/System/out Ljava/io/PrintStream;",
-      "ldc \"" + message + "\"",
-      "invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V",
-      "return"
-    };
-  }
-}
-
-class NonVirtualOverrideTestClass {
-
-  public static void main(String[] args) {
-    A a = new B();
-    a.m1();
-    a.m2();
-    a.m3();
-    a.m4();
-
-    a = new C();
-    a.m1();
-    a.m2();
-    a.m3();
-    a.m4();
-
-    B b = new B();
-    try {
-      b.m1();
-    } catch (IllegalAccessError exception) {
-      System.out.println("Caught IllegalAccessError when calling B.m1()");
-    }
-    try {
-      b.m3();
-    } catch (IncompatibleClassChangeError exception) {
-      System.out.println("Caught IncompatibleClassChangeError when calling B.m3()");
-    }
-
-    try {
-      b = new C();
-      b.m1();
-    } catch (IllegalAccessError exception) {
-      System.out.println("Caught IllegalAccessError when calling B.m1()");
-    }
-    try {
-      b = new C();
-      b.m3();
-    } catch (IncompatibleClassChangeError exception) {
-      System.out.println("Caught IncompatibleClassChangeError when calling B.m3()");
-    }
-
-    C c = new C();
-    c.m1();
-    c.m3();
-  }
-
-  static class A {
-
-    public void m1() {
-      System.out.println("In A.m1()");
-    }
-
-    public void m2() {
-      System.out.println("In A.m2()");
-    }
-
-    public void m3() {
-      System.out.println("In A.m3()");
-    }
-
-    public void m4() {
-      System.out.println("In A.m4()");
-    }
-  }
-
-  static class B extends A {
-
-    // Will be made private with Jasmin. This method is targeted and can therefore not be removed.
-    public void m1() {
-      System.out.println("In B.m1()");
-    }
-
-    // Will be made private with Jasmin. Ends up being dead code because the method is never called.
-    public void m2() {
-      System.out.println("In B.m2()");
-    }
-
-    // Will be made static with Jasmin. This method is targeted and can therefore not be removed.
-    public void m3() {
-      System.out.println("In B.m3()");
-    }
-
-    // Will be made static with Jasmin. Ends up being dead code because the method is never called.
-    public void m4() {
-      System.out.println("In B.m4()");
-    }
-  }
-
-  static class C extends B {
-
-    public void m1() {
-      System.out.println("In C.m1()");
-    }
-
-    public void m3() {
-      System.out.println("In C.m3()");
-    }
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTestDump.java b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTestDump.java
new file mode 100644
index 0000000..e8f54b3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTestDump.java
@@ -0,0 +1,726 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.shaking;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+class NonVirtualOverrideTestClass {
+
+  public static void main(String[] args) {
+    A a = new B();
+    a.m1();
+    a.m2();
+    a.m3();
+    a.m4();
+
+    a = new C();
+    a.m1();
+    a.m2();
+    a.m3();
+    a.m4();
+
+    B b = new B();
+    try {
+      b.m1();
+    } catch (IllegalAccessError exception) {
+      System.out.println("Caught IllegalAccessError when calling B.m1()");
+    }
+    try {
+      b.m3();
+    } catch (IncompatibleClassChangeError exception) {
+      System.out.println("Caught IncompatibleClassChangeError when calling B.m3()");
+    }
+
+    try {
+      b = new C();
+      b.m1();
+    } catch (IllegalAccessError exception) {
+      System.out.println("Caught IllegalAccessError when calling B.m1()");
+    }
+    try {
+      b = new C();
+      b.m3();
+    } catch (IncompatibleClassChangeError exception) {
+      System.out.println("Caught IncompatibleClassChangeError when calling B.m3()");
+    }
+
+    C c = new C();
+    c.m1();
+    c.m3();
+  }
+}
+
+class A {
+
+  public void m1() {
+    System.out.println("In A.m1()");
+  }
+
+  public void m2() {
+    System.out.println("In A.m2()");
+  }
+
+  public void m3() {
+    System.out.println("In A.m3()");
+  }
+
+  public void m4() {
+    System.out.println("In A.m4()");
+  }
+}
+
+class B extends A {
+
+  // Made private in the dump below. This method is targeted and can therefore not be removed.
+  public void m1() {
+    System.out.println("In B.m1()");
+  }
+
+  // Made private in the dump below. Ends up being dead code because the method is never called.
+  public void m2() {
+    System.out.println("In B.m2()");
+  }
+
+  // Made static in the dump below. This method is targeted and can therefore not be removed.
+  public void m3() {
+    System.out.println("In B.m3()");
+  }
+
+  // Made static in the dump below. Ends up being dead code because the method is never called.
+  public void m4() {
+    System.out.println("In B.m4()");
+  }
+}
+
+class C extends B {
+
+  public void m1() {
+    System.out.println("In C.m1()");
+  }
+
+  public void m3() {
+    System.out.println("In C.m3()");
+  }
+}
+
+/* Below are dumps from the classes above with the changes to B as described */
+
+class NonVirtualOverrideTestClassDump implements Opcodes {
+
+  public static byte[] dump() {
+
+    ClassWriter classWriter = new ClassWriter(0);
+    MethodVisitor methodVisitor;
+
+    classWriter.visit(
+        V1_8,
+        ACC_SUPER,
+        "com/android/tools/r8/shaking/NonVirtualOverrideTestClass",
+        null,
+        "java/lang/Object",
+        null);
+
+    classWriter.visitSource("NonVirtualOverrideTestDump.java", null);
+
+    {
+      methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(7, label0);
+      methodVisitor.visitVarInsn(ALOAD, 0);
+      methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+      methodVisitor.visitInsn(RETURN);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLocalVariable(
+          "this",
+          "Lcom/android/tools/r8/shaking/NonVirtualOverrideTestClass;",
+          null,
+          label0,
+          label1,
+          0);
+      methodVisitor.visitMaxs(1, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor =
+          classWriter.visitMethod(
+              ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      Label label1 = new Label();
+      Label label2 = new Label();
+      methodVisitor.visitTryCatchBlock(label0, label1, label2, "java/lang/IllegalAccessError");
+      Label label3 = new Label();
+      Label label4 = new Label();
+      Label label5 = new Label();
+      methodVisitor.visitTryCatchBlock(
+          label3, label4, label5, "java/lang/IncompatibleClassChangeError");
+      Label label6 = new Label();
+      Label label7 = new Label();
+      Label label8 = new Label();
+      methodVisitor.visitTryCatchBlock(label6, label7, label8, "java/lang/IllegalAccessError");
+      Label label9 = new Label();
+      Label label10 = new Label();
+      Label label11 = new Label();
+      methodVisitor.visitTryCatchBlock(
+          label9, label10, label11, "java/lang/IncompatibleClassChangeError");
+      Label label12 = new Label();
+      methodVisitor.visitLabel(label12);
+      methodVisitor.visitLineNumber(10, label12);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/B");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/B", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 1);
+      Label label13 = new Label();
+      methodVisitor.visitLabel(label13);
+      methodVisitor.visitLineNumber(11, label13);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m1", "()V", false);
+      Label label14 = new Label();
+      methodVisitor.visitLabel(label14);
+      methodVisitor.visitLineNumber(12, label14);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m2", "()V", false);
+      Label label15 = new Label();
+      methodVisitor.visitLabel(label15);
+      methodVisitor.visitLineNumber(13, label15);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m3", "()V", false);
+      Label label16 = new Label();
+      methodVisitor.visitLabel(label16);
+      methodVisitor.visitLineNumber(14, label16);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m4", "()V", false);
+      Label label17 = new Label();
+      methodVisitor.visitLabel(label17);
+      methodVisitor.visitLineNumber(16, label17);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/C");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/C", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 1);
+      Label label18 = new Label();
+      methodVisitor.visitLabel(label18);
+      methodVisitor.visitLineNumber(17, label18);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m1", "()V", false);
+      Label label19 = new Label();
+      methodVisitor.visitLabel(label19);
+      methodVisitor.visitLineNumber(18, label19);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m2", "()V", false);
+      Label label20 = new Label();
+      methodVisitor.visitLabel(label20);
+      methodVisitor.visitLineNumber(19, label20);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m3", "()V", false);
+      Label label21 = new Label();
+      methodVisitor.visitLabel(label21);
+      methodVisitor.visitLineNumber(20, label21);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m4", "()V", false);
+      Label label22 = new Label();
+      methodVisitor.visitLabel(label22);
+      methodVisitor.visitLineNumber(22, label22);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/B");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/B", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 2);
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(24, label0);
+      methodVisitor.visitVarInsn(ALOAD, 2);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/B", "m1", "()V", false);
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(27, label1);
+      methodVisitor.visitJumpInsn(GOTO, label3);
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLineNumber(25, label2);
+      methodVisitor.visitFrame(
+          Opcodes.F_FULL,
+          3,
+          new Object[] {
+            "[Ljava/lang/String;",
+            "com/android/tools/r8/shaking/A",
+            "com/android/tools/r8/shaking/B"
+          },
+          1,
+          new Object[] {"java/lang/IllegalAccessError"});
+      methodVisitor.visitVarInsn(ASTORE, 3);
+      Label label23 = new Label();
+      methodVisitor.visitLabel(label23);
+      methodVisitor.visitLineNumber(26, label23);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("Caught IllegalAccessError when calling B.m1()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      methodVisitor.visitLabel(label3);
+      methodVisitor.visitLineNumber(29, label3);
+      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      methodVisitor.visitVarInsn(ALOAD, 2);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/B", "m3", "()V", false);
+      methodVisitor.visitLabel(label4);
+      methodVisitor.visitLineNumber(32, label4);
+      methodVisitor.visitJumpInsn(GOTO, label6);
+      methodVisitor.visitLabel(label5);
+      methodVisitor.visitLineNumber(30, label5);
+      methodVisitor.visitFrame(
+          Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IncompatibleClassChangeError"});
+      methodVisitor.visitVarInsn(ASTORE, 3);
+      Label label24 = new Label();
+      methodVisitor.visitLabel(label24);
+      methodVisitor.visitLineNumber(31, label24);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("Caught IncompatibleClassChangeError when calling B.m3()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      methodVisitor.visitLabel(label6);
+      methodVisitor.visitLineNumber(35, label6);
+      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/C");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/C", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 2);
+      Label label25 = new Label();
+      methodVisitor.visitLabel(label25);
+      methodVisitor.visitLineNumber(36, label25);
+      methodVisitor.visitVarInsn(ALOAD, 2);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/B", "m1", "()V", false);
+      methodVisitor.visitLabel(label7);
+      methodVisitor.visitLineNumber(39, label7);
+      methodVisitor.visitJumpInsn(GOTO, label9);
+      methodVisitor.visitLabel(label8);
+      methodVisitor.visitLineNumber(37, label8);
+      methodVisitor.visitFrame(
+          Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IllegalAccessError"});
+      methodVisitor.visitVarInsn(ASTORE, 3);
+      Label label26 = new Label();
+      methodVisitor.visitLabel(label26);
+      methodVisitor.visitLineNumber(38, label26);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("Caught IllegalAccessError when calling B.m1()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      methodVisitor.visitLabel(label9);
+      methodVisitor.visitLineNumber(41, label9);
+      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/C");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/C", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 2);
+      Label label27 = new Label();
+      methodVisitor.visitLabel(label27);
+      methodVisitor.visitLineNumber(42, label27);
+      methodVisitor.visitVarInsn(ALOAD, 2);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/B", "m3", "()V", false);
+      methodVisitor.visitLabel(label10);
+      methodVisitor.visitLineNumber(45, label10);
+      Label label28 = new Label();
+      methodVisitor.visitJumpInsn(GOTO, label28);
+      methodVisitor.visitLabel(label11);
+      methodVisitor.visitLineNumber(43, label11);
+      methodVisitor.visitFrame(
+          Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IncompatibleClassChangeError"});
+      methodVisitor.visitVarInsn(ASTORE, 3);
+      Label label29 = new Label();
+      methodVisitor.visitLabel(label29);
+      methodVisitor.visitLineNumber(44, label29);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("Caught IncompatibleClassChangeError when calling B.m3()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      methodVisitor.visitLabel(label28);
+      methodVisitor.visitLineNumber(47, label28);
+      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/C");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/C", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 3);
+      Label label30 = new Label();
+      methodVisitor.visitLabel(label30);
+      methodVisitor.visitLineNumber(48, label30);
+      methodVisitor.visitVarInsn(ALOAD, 3);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/C", "m1", "()V", false);
+      Label label31 = new Label();
+      methodVisitor.visitLabel(label31);
+      methodVisitor.visitLineNumber(49, label31);
+      methodVisitor.visitVarInsn(ALOAD, 3);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/C", "m3", "()V", false);
+      Label label32 = new Label();
+      methodVisitor.visitLabel(label32);
+      methodVisitor.visitLineNumber(50, label32);
+      methodVisitor.visitInsn(RETURN);
+      Label label33 = new Label();
+      methodVisitor.visitLabel(label33);
+      methodVisitor.visitLocalVariable(
+          "exception", "Ljava/lang/IllegalAccessError;", null, label23, label3, 3);
+      methodVisitor.visitLocalVariable(
+          "exception", "Ljava/lang/IncompatibleClassChangeError;", null, label24, label6, 3);
+      methodVisitor.visitLocalVariable(
+          "exception", "Ljava/lang/IllegalAccessError;", null, label26, label9, 3);
+      methodVisitor.visitLocalVariable(
+          "exception", "Ljava/lang/IncompatibleClassChangeError;", null, label29, label28, 3);
+      methodVisitor.visitLocalVariable("args", "[Ljava/lang/String;", null, label12, label33, 0);
+      methodVisitor.visitLocalVariable(
+          "a", "Lcom/android/tools/r8/shaking/A;", null, label13, label33, 1);
+      methodVisitor.visitLocalVariable(
+          "b", "Lcom/android/tools/r8/shaking/B;", null, label0, label33, 2);
+      methodVisitor.visitLocalVariable(
+          "c", "Lcom/android/tools/r8/shaking/C;", null, label30, label33, 3);
+      methodVisitor.visitMaxs(2, 4);
+      methodVisitor.visitEnd();
+    }
+    classWriter.visitEnd();
+
+    return classWriter.toByteArray();
+  }
+}
+
+class ADump implements Opcodes {
+
+  public static byte[] dump() {
+
+    ClassWriter classWriter = new ClassWriter(0);
+    MethodVisitor methodVisitor;
+
+    classWriter.visit(
+        V1_8, ACC_SUPER, "com/android/tools/r8/shaking/A", null, "java/lang/Object", null);
+
+    classWriter.visitSource("NonVirtualOverrideTestDump.java", null);
+
+    {
+      methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(53, label0);
+      methodVisitor.visitVarInsn(ALOAD, 0);
+      methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+      methodVisitor.visitInsn(RETURN);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/A;", null, label0, label1, 0);
+      methodVisitor.visitMaxs(1, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m1", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(56, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In A.m1()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(57, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/A;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m2", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(60, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In A.m2()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(61, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/A;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m3", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(64, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In A.m3()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(65, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/A;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m4", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(68, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In A.m4()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(69, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/A;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    classWriter.visitEnd();
+
+    return classWriter.toByteArray();
+  }
+}
+
+class BDump implements Opcodes {
+
+  public static byte[] dump() {
+
+    ClassWriter classWriter = new ClassWriter(0);
+    MethodVisitor methodVisitor;
+
+    classWriter.visit(
+        V1_8,
+        ACC_SUPER,
+        "com/android/tools/r8/shaking/B",
+        null,
+        "com/android/tools/r8/shaking/A",
+        null);
+
+    classWriter.visitSource("NonVirtualOverrideTestDump.java", null);
+
+    {
+      methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(72, label0);
+      methodVisitor.visitVarInsn(ALOAD, 0);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/A", "<init>", "()V", false);
+      methodVisitor.visitInsn(RETURN);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/B;", null, label0, label1, 0);
+      methodVisitor.visitMaxs(1, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PRIVATE, "m1", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(76, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In B.m1()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(77, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/B;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PRIVATE, "m2", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(81, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In B.m2()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(82, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/B;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_STATIC, "m3", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(86, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In B.m3()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(87, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/B;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_STATIC, "m4", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(91, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In B.m4()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(92, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/B;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    classWriter.visitEnd();
+
+    return classWriter.toByteArray();
+  }
+}
+
+class CDump implements Opcodes {
+
+  public static byte[] dump() {
+
+    ClassWriter classWriter = new ClassWriter(0);
+    MethodVisitor methodVisitor;
+
+    classWriter.visit(
+        V1_8,
+        ACC_SUPER,
+        "com/android/tools/r8/shaking/C",
+        null,
+        "com/android/tools/r8/shaking/B",
+        null);
+
+    classWriter.visitSource("NonVirtualOverrideTestDump.java", null);
+
+    {
+      methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(95, label0);
+      methodVisitor.visitVarInsn(ALOAD, 0);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/B", "<init>", "()V", false);
+      methodVisitor.visitInsn(RETURN);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/C;", null, label0, label1, 0);
+      methodVisitor.visitMaxs(1, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m1", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(98, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In C.m1()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(99, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/C;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m3", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(102, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In C.m3()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(103, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/C;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    classWriter.visitEnd();
+
+    return classWriter.toByteArray();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java b/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
index 1f6a0c0..8247e92 100644
--- a/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
@@ -94,7 +94,7 @@
     inspections.put("shaking12:keep-rules-printusage.txt", PrintUsageTest::inspectShaking12);
 
     List<Object[]> testCases = new ArrayList<>();
-    for (Backend backend : Backend.values()) {
+    for (Backend backend : ToolHelper.getBackends()) {
       Set<String> usedInspections = new HashSet<>();
       for (String test : tests) {
         File[] keepFiles = new File(ToolHelper.EXAMPLES_DIR + test)
diff --git a/src/test/java/com/android/tools/r8/shaking/ServiceLoaderTest.java b/src/test/java/com/android/tools/r8/shaking/ServiceLoaderTest.java
index ac4ac5f..1f2de23 100644
--- a/src/test/java/com/android/tools/r8/shaking/ServiceLoaderTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ServiceLoaderTest.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.DataEntryResource;
 import com.android.tools.r8.R8TestRunResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.naming.AdaptResourceFileContentsTest.DataResourceConsumerForTesting;
 import com.android.tools.r8.origin.Origin;
@@ -44,7 +45,7 @@
 
   @Parameters(name = "Backend: {0}, include WorldGreeter: {1}")
   public static List<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   public ServiceLoaderTest(Backend backend, boolean includeWorldGreeter) {
diff --git a/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java b/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java
index cc0e5cf..9290085 100644
--- a/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java
@@ -8,6 +8,7 @@
 
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.FieldSubject;
 import com.google.common.collect.ImmutableList;
@@ -25,7 +26,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public AnnotationsOnFieldsTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnTargetedMethodTest.java b/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnTargetedMethodTest.java
index a7bdf0b..d727ce3 100644
--- a/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnTargetedMethodTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnTargetedMethodTest.java
@@ -35,7 +35,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public AnnotationsOnTargetedMethodTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/annotations/ReflectiveAnnotationUseTest.java b/src/test/java/com/android/tools/r8/shaking/annotations/ReflectiveAnnotationUseTest.java
index 7af0624..e08e8f7 100644
--- a/src/test/java/com/android/tools/r8/shaking/annotations/ReflectiveAnnotationUseTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/annotations/ReflectiveAnnotationUseTest.java
@@ -12,6 +12,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.KotlinTestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
 import com.android.tools.r8.graph.DexAnnotationElement;
 import com.android.tools.r8.utils.AndroidApp;
@@ -60,7 +61,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} target: {1} minify: {2}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), KotlinTargetVersion.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), KotlinTargetVersion.values(), BooleanUtils.values());
   }
 
   public ReflectiveAnnotationUseTest(
diff --git a/src/test/java/com/android/tools/r8/shaking/assumevalues/SynthesizedRulesFromApiLevelTest.java b/src/test/java/com/android/tools/r8/shaking/assumevalues/SynthesizedRulesFromApiLevelTest.java
index ffe6c21..610f63b 100644
--- a/src/test/java/com/android/tools/r8/shaking/assumevalues/SynthesizedRulesFromApiLevelTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/assumevalues/SynthesizedRulesFromApiLevelTest.java
@@ -48,7 +48,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   // Simple mock implementation of class android.os.Build$VERSION with just the SDK_INT field.
diff --git a/src/test/java/com/android/tools/r8/shaking/defaultmethods/DefaultMethodsTest.java b/src/test/java/com/android/tools/r8/shaking/defaultmethods/DefaultMethodsTest.java
index 424a5b7..b2e44c3 100644
--- a/src/test/java/com/android/tools/r8/shaking/defaultmethods/DefaultMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/defaultmethods/DefaultMethodsTest.java
@@ -32,7 +32,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public DefaultMethodsTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ForceProguardCompatibilityTest.java b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ForceProguardCompatibilityTest.java
index 906aee9..76fd865 100644
--- a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ForceProguardCompatibilityTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ForceProguardCompatibilityTest.java
@@ -53,7 +53,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ForceProguardCompatibilityTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/defaultctor/ImplicitlyKeptDefaultConstructorTest.java b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/defaultctor/ImplicitlyKeptDefaultConstructorTest.java
index 6e206e4..b17258b 100644
--- a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/defaultctor/ImplicitlyKeptDefaultConstructorTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/defaultctor/ImplicitlyKeptDefaultConstructorTest.java
@@ -11,6 +11,7 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.shaking.forceproguardcompatibility.ProguardCompatibilityTestBase;
 import com.android.tools.r8.smali.ConstantFoldingTest.TriConsumer;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -101,7 +102,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ImplicitlyKeptDefaultConstructorTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/accessrelaxation/IfRuleWithAccessRelaxationTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/accessrelaxation/IfRuleWithAccessRelaxationTest.java
index 560ebd4..9e49df9 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/accessrelaxation/IfRuleWithAccessRelaxationTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/accessrelaxation/IfRuleWithAccessRelaxationTest.java
@@ -13,6 +13,7 @@
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -30,7 +31,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/classinlining/IfRuleWithClassInlining.java b/src/test/java/com/android/tools/r8/shaking/ifrule/classinlining/IfRuleWithClassInlining.java
index caa06d3..cb06b0e 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/classinlining/IfRuleWithClassInlining.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/classinlining/IfRuleWithClassInlining.java
@@ -9,6 +9,7 @@
 import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -34,7 +35,7 @@
 
   @Parameters(name = "Backend: {0}, class inlining: {1}, with if rule: {2}")
   public static List<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values(), BooleanUtils.values());
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/classstaticizer/IfRuleWithClassStaticizerTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/classstaticizer/IfRuleWithClassStaticizerTest.java
index a12620d..f5b1a29 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/classstaticizer/IfRuleWithClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/classstaticizer/IfRuleWithClassStaticizerTest.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -30,7 +31,7 @@
 
   @Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public IfRuleWithClassStaticizerTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java
index 2d9027d..9c2b567 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java
@@ -10,6 +10,7 @@
 
 import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringUtils;
@@ -78,7 +79,7 @@
   @Parameters(name = "Backend: {0}, vertical class merging: {1}")
   public static Collection<Object[]> data() {
     // We don't run this on Proguard, as Proguard does not merge A into B.
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   private void configure(InternalOptions options) {
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedTypeBaseTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedTypeBaseTest.java
index 4fa2440..d10f029 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedTypeBaseTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedTypeBaseTest.java
@@ -10,6 +10,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -60,7 +61,7 @@
   @Parameters(name = "Backend: {0}, vertical class merging: {1}")
   public static Collection<Object[]> data() {
     // We don't run this on Proguard, as Proguard does not merge A into B.
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   public abstract Class<?> getTestClass();
diff --git a/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepClassMembersTest.java b/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepClassMembersTest.java
index 5537869..a0b9fb3 100644
--- a/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepClassMembersTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepClassMembersTest.java
@@ -11,6 +11,7 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.shaking.forceproguardcompatibility.ProguardCompatibilityTestBase;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -28,7 +29,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public KeepClassMembersTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByAnnotatedClassTestRunner.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByAnnotatedClassTestRunner.java
index c758507..47659e2 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByAnnotatedClassTestRunner.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByAnnotatedClassTestRunner.java
@@ -7,6 +7,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.utils.StringUtils;
@@ -27,7 +28,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public KeptByAnnotatedClassTestRunner(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByAnnotatedMethodTestRunner.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByAnnotatedMethodTestRunner.java
index a7e3e46..dddc278 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByAnnotatedMethodTestRunner.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByAnnotatedMethodTestRunner.java
@@ -7,6 +7,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.references.Reference;
@@ -33,7 +34,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public KeptByAnnotatedMethodTestRunner(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByFieldReflectionTestRunner.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByFieldReflectionTestRunner.java
index 6ba1f08..a2d5ba7 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByFieldReflectionTestRunner.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByFieldReflectionTestRunner.java
@@ -8,6 +8,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.references.FieldReference;
 import com.android.tools.r8.references.MethodReference;
@@ -44,7 +45,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public KeptByFieldReflectionTestRunner(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByMethodReflectionTestRunner.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByMethodReflectionTestRunner.java
index 3224689..4f226fe 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByMethodReflectionTestRunner.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByMethodReflectionTestRunner.java
@@ -7,6 +7,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.shaking.WhyAreYouKeepingConsumer;
@@ -42,7 +43,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public KeptByMethodReflectionTestRunner(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoRulesTestRunner.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoRulesTestRunner.java
index 38c3f00..975361e 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoRulesTestRunner.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoRulesTestRunner.java
@@ -8,6 +8,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.graphinspector.GraphInspector;
@@ -31,7 +32,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public KeptByTwoRulesTestRunner(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptMethodTestRunner.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptMethodTestRunner.java
index 04d5706..81ba033 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptMethodTestRunner.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptMethodTestRunner.java
@@ -7,6 +7,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.utils.StringUtils;
@@ -27,7 +28,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public KeptMethodTestRunner(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptViaClassInitializerTestRunner.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptViaClassInitializerTestRunner.java
index 50ee3e2..0e61231 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptViaClassInitializerTestRunner.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptViaClassInitializerTestRunner.java
@@ -73,7 +73,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public KeptViaClassInitializerTestRunner(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/RemovedClassTestRunner.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/RemovedClassTestRunner.java
index c555b7e..37ba854 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/RemovedClassTestRunner.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/RemovedClassTestRunner.java
@@ -9,6 +9,7 @@
 
 import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.utils.StringUtils;
@@ -37,7 +38,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public RemovedClassTestRunner(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/proxy/MockitoTest.java b/src/test/java/com/android/tools/r8/shaking/proxy/MockitoTest.java
index bb6f828..1d6b5b0 100644
--- a/src/test/java/com/android/tools/r8/shaking/proxy/MockitoTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/proxy/MockitoTest.java
@@ -35,7 +35,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0} minify: {1}")
   public static Collection<Object[]> data() {
-    return buildParameters(Backend.values(), BooleanUtils.values());
+    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values());
   }
 
   public MockitoTest(Backend backend, boolean minify) {
diff --git a/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java b/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java
index 8896d25..0fe8d7e 100644
--- a/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java
@@ -40,7 +40,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ProxiesTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/reflection/FieldAccessTest.java b/src/test/java/com/android/tools/r8/shaking/reflection/FieldAccessTest.java
index 7aa573e..dd8dd90 100644
--- a/src/test/java/com/android/tools/r8/shaking/reflection/FieldAccessTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/reflection/FieldAccessTest.java
@@ -8,6 +8,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.references.FieldReference;
 import com.android.tools.r8.references.MethodReference;
@@ -26,7 +27,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public FieldAccessTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/synthetic/StaticCallInSyntheticMethodAsmTest.java b/src/test/java/com/android/tools/r8/shaking/synthetic/StaticCallInSyntheticMethodAsmTest.java
index b08be31..d0968c5 100644
--- a/src/test/java/com/android/tools/r8/shaking/synthetic/StaticCallInSyntheticMethodAsmTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/synthetic/StaticCallInSyntheticMethodAsmTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.shaking.synthetic;
 
 import com.android.tools.r8.AsmTestBase;
+import com.android.tools.r8.ToolHelper;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -14,7 +15,7 @@
 
   @Parameterized.Parameters(name = "backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public StaticCallInSyntheticMethodAsmTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java b/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java
index 4bfdd16..3c23ef6 100644
--- a/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java
@@ -14,6 +14,7 @@
 import static org.junit.Assert.fail;
 
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.google.common.collect.ImmutableList;
@@ -28,7 +29,7 @@
 
   @Parameterized.Parameters(name = "Backend: {0}")
   public static Backend[] data() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public ForceInlineTest(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/shaking/whyareyoukeeping/WhyAreYouKeepingTest.java b/src/test/java/com/android/tools/r8/shaking/whyareyoukeeping/WhyAreYouKeepingTest.java
index 2a5a6f6..87f73bd 100644
--- a/src/test/java/com/android/tools/r8/shaking/whyareyoukeeping/WhyAreYouKeepingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/whyareyoukeeping/WhyAreYouKeepingTest.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.references.Reference;
 import com.android.tools.r8.shaking.WhyAreYouKeepingConsumer;
 import com.android.tools.r8.utils.StringUtils;
@@ -58,7 +59,7 @@
 
   @Parameters(name = "{0}")
   public static Backend[] parameters() {
-    return Backend.values();
+    return ToolHelper.getBackends();
   }
 
   public final Backend backend;
diff --git a/src/test/java/com/android/tools/r8/smali/DexMoveInstructionsTest.java b/src/test/java/com/android/tools/r8/smali/DexMoveInstructionsTest.java
index c92b73b..677d57a 100644
--- a/src/test/java/com/android/tools/r8/smali/DexMoveInstructionsTest.java
+++ b/src/test/java/com/android/tools/r8/smali/DexMoveInstructionsTest.java
@@ -9,6 +9,7 @@
 
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -88,7 +89,7 @@
       main.add("  invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(" + typeDesc + ")V");
     }
     main.add("  return-void");
-    builder.addMainMethod(3, main.toArray(new String[0]));
+    builder.addMainMethod(3, main.toArray(StringUtils.EMPTY_ARRAY));
 
     return runOnArtRaw(builder.build(), clazz);
   }
diff --git a/src/test/java/com/android/tools/r8/smali/IfZeroObjectTest.java b/src/test/java/com/android/tools/r8/smali/IfZeroObjectTest.java
index ebcd835..6211aec 100644
--- a/src/test/java/com/android/tools/r8/smali/IfZeroObjectTest.java
+++ b/src/test/java/com/android/tools/r8/smali/IfZeroObjectTest.java
@@ -8,6 +8,7 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.utils.StringUtils;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -61,7 +62,7 @@
       main.add("  invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(I)V");
     }
     main.add("  return-void");
-    builder.addMainMethod(2, main.toArray(new String[0]));
+    builder.addMainMethod(2, main.toArray(StringUtils.EMPTY_ARRAY));
 
     return runOnArtRaw(builder.build(), clazz);
   }
diff --git a/src/test/java/com/android/tools/r8/smali/OutlineTest.java b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
index bfeac7a..5d524af 100644
--- a/src/test/java/com/android/tools/r8/smali/OutlineTest.java
+++ b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
@@ -36,6 +36,7 @@
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
+import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
@@ -1586,7 +1587,7 @@
         DEFAULT_METHOD_NAME + "1",
         parameters,
         0,
-        codeToOutline.toArray(new String[0])
+        codeToOutline.toArray(StringUtils.EMPTY_ARRAY)
     );
 
     MethodSignature signature2 = builder.addPrivateInstanceMethod(
@@ -1594,7 +1595,7 @@
         DEFAULT_METHOD_NAME + "2",
         parameters,
         0,
-        codeToOutline.toArray(new String[0])
+        codeToOutline.toArray(StringUtils.EMPTY_ARRAY)
     );
 
     builder.addMainMethod(
@@ -1661,7 +1662,7 @@
         DEFAULT_METHOD_NAME + "1",
         parameters,
         0,
-        codeToOutline.toArray(new String[0])
+        codeToOutline.toArray(StringUtils.EMPTY_ARRAY)
     );
 
     MethodSignature signature2 = builder.addPrivateInstanceMethod(
@@ -1669,7 +1670,7 @@
         DEFAULT_METHOD_NAME + "2",
         parameters,
         0,
-        codeToOutline.toArray(new String[0])
+        codeToOutline.toArray(StringUtils.EMPTY_ARRAY)
     );
 
     builder.addMainMethod(
@@ -1733,7 +1734,7 @@
         DEFAULT_METHOD_NAME + "1",
         parameters,
         0,
-        codeToOutline.toArray(new String[0])
+        codeToOutline.toArray(StringUtils.EMPTY_ARRAY)
     );
 
     MethodSignature signature2 = builder.addPrivateInstanceMethod(
@@ -1741,7 +1742,7 @@
         DEFAULT_METHOD_NAME + "2",
         parameters,
         0,
-        codeToOutline.toArray(new String[0])
+        codeToOutline.toArray(StringUtils.EMPTY_ARRAY)
     );
 
     builder.addMainMethod(
@@ -1805,7 +1806,7 @@
         DEFAULT_METHOD_NAME + "1",
         parameters,
         0,
-        codeToOutline.toArray(new String[0])
+        codeToOutline.toArray(StringUtils.EMPTY_ARRAY)
     );
 
     MethodSignature signature2 = builder.addPrivateInstanceMethod(
@@ -1813,7 +1814,7 @@
         DEFAULT_METHOD_NAME + "2",
         parameters,
         0,
-        codeToOutline.toArray(new String[0])
+        codeToOutline.toArray(StringUtils.EMPTY_ARRAY)
     );
 
     builder.addMainMethod(
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
index 0fb0b30..6b3cf1e 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
@@ -19,6 +19,7 @@
 import com.android.tools.r8.naming.MemberNaming.Signature;
 import com.android.tools.r8.naming.signature.GenericSignatureParser;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
 import java.util.Arrays;
 import java.util.List;
 import java.util.function.Consumer;
@@ -70,9 +71,8 @@
         codeInspector.dexItemFactory.createProto(
             codeInspector.toDexType(codeInspector.getObfuscatedTypeName(returnType)), parameterTypes);
     if (naming != null) {
-      String[] parameterStrings = new String[parameterTypes.length];
       Signature signature =
-          new MethodSignature(name, returnType, parameters.toArray(parameterStrings));
+          new MethodSignature(name, returnType, parameters.toArray(StringUtils.EMPTY_ARRAY));
       MemberNaming methodNaming = naming.lookupByOriginalSignature(signature);
       if (methodNaming != null) {
         name = methodNaming.getRenamedName();