Merge "Create an ART-independent DexFileLoader"
diff --git a/compiler/utils/test_dex_file_builder.h b/compiler/utils/test_dex_file_builder.h
index 04fba51..58f1ec7 100644
--- a/compiler/utils/test_dex_file_builder.h
+++ b/compiler/utils/test_dex_file_builder.h
@@ -27,6 +27,7 @@
 #include <android-base/logging.h>
 
 #include "base/bit_utils.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file_loader.h"
 #include "dex/standard_dex_file.h"
 
@@ -233,7 +234,8 @@
     static constexpr bool kVerify = false;
     static constexpr bool kVerifyChecksum = false;
     std::string error_msg;
-    std::unique_ptr<const DexFile> dex_file(DexFileLoader::Open(
+    const ArtDexFileLoader dex_file_loader;
+    std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(
         &dex_file_data_[0],
         dex_file_data_.size(),
         dex_location,
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index 980363b..05592f1 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -29,6 +29,7 @@
 #include "base/file_utils.h"
 #include "base/macros.h"
 #include "base/unix_file/fd_file.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
 #include "jit/profile_compilation_info.h"
@@ -65,12 +66,13 @@
     for (const std::string& dex : GetLibCoreDexFileNames()) {
       std::vector<std::unique_ptr<const DexFile>> dex_files;
       std::string error_msg;
-      CHECK(DexFileLoader::Open(dex.c_str(),
-                                dex,
-                                /*verify*/ true,
-                                /*verify_checksum*/ false,
-                                &error_msg,
-                                &dex_files))
+      const ArtDexFileLoader dex_file_loader;
+      CHECK(dex_file_loader.Open(dex.c_str(),
+                                 dex,
+                                 /*verify*/ true,
+                                 /*verify_checksum*/ false,
+                                 &error_msg,
+                                 &dex_files))
           << error_msg;
       for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
         for (size_t i = 0; i < dex_file->NumMethodIds(); ++i) {
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index e98cb74..8799540 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -30,6 +30,7 @@
 #include "base/macros.h"
 #include "base/mutex-inl.h"
 #include "bytecode_utils.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/code_item_accessors-inl.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
@@ -684,7 +685,8 @@
     const char* location = dex_location.c_str();
     std::string error_msg;
     std::vector<std::unique_ptr<const DexFile>> dex_files;
-    ASSERT_TRUE(DexFileLoader::Open(
+    const ArtDexFileLoader dex_file_loader;
+    ASSERT_TRUE(dex_file_loader.Open(
         location, location, /* verify */ true, /* verify_checksum */ true, &error_msg, &dex_files));
     EXPECT_EQ(dex_files.size(), 1U);
     std::unique_ptr<const DexFile>& dex_file = dex_files[0];
@@ -819,7 +821,8 @@
 
     const char* location = dex_location.c_str();
     std::vector<std::unique_ptr<const DexFile>> dex_files;
-    ASSERT_TRUE(DexFileLoader::Open(
+    const ArtDexFileLoader dex_file_loader;
+    ASSERT_TRUE(dex_file_loader.Open(
         location, location, /* verify */ true, /* verify_checksum */ true, &error_msg, &dex_files));
     EXPECT_EQ(dex_files.size(), 1U);
     std::unique_ptr<const DexFile>& old_dex_file = dex_files[0];
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 16d70da..cecd376 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -33,6 +33,7 @@
 #include "class_table-inl.h"
 #include "compiled_method-inl.h"
 #include "debug/method_debug_info.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
 #include "dex/dex_file_types.h"
@@ -3392,6 +3393,7 @@
   std::string error_msg;
   std::string location(oat_dex_file->GetLocation());
   std::unique_ptr<const DexFile> dex_file;
+  const ArtDexFileLoader dex_file_loader;
   if (oat_dex_file->source_.IsZipEntry()) {
     ZipEntry* zip_entry = oat_dex_file->source_.GetZipEntry();
     std::unique_ptr<MemMap> mem_map(
@@ -3400,12 +3402,12 @@
       LOG(ERROR) << "Failed to extract dex file to mem map for layout: " << error_msg;
       return false;
     }
-    dex_file = DexFileLoader::Open(location,
-                                   zip_entry->GetCrc32(),
-                                   std::move(mem_map),
-                                   /* verify */ true,
-                                   /* verify_checksum */ true,
-                                   &error_msg);
+    dex_file = dex_file_loader.Open(location,
+                               zip_entry->GetCrc32(),
+                               std::move(mem_map),
+                               /* verify */ true,
+                               /* verify_checksum */ true,
+                               &error_msg);
   } else if (oat_dex_file->source_.IsRawFile()) {
     File* raw_file = oat_dex_file->source_.GetRawFile();
     int dup_fd = dup(raw_file->Fd());
@@ -3413,7 +3415,7 @@
       PLOG(ERROR) << "Failed to dup dex file descriptor (" << raw_file->Fd() << ") at " << location;
       return false;
     }
-    dex_file = DexFileLoader::OpenDex(
+    dex_file = dex_file_loader.OpenDex(
         dup_fd, location, /* verify */ true, /* verify_checksum */ true, &error_msg);
   } else {
     // The source data is a vdex file.
@@ -3426,14 +3428,14 @@
     DCHECK(ValidateDexFileHeader(raw_dex_file, oat_dex_file->GetLocation()));
     const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file);
     // Since the source may have had its layout changed, or may be quickened, don't verify it.
-    dex_file = DexFileLoader::Open(raw_dex_file,
-                                   header->file_size_,
-                                   location,
-                                   oat_dex_file->dex_file_location_checksum_,
-                                   nullptr,
-                                   /* verify */ false,
-                                   /* verify_checksum */ false,
-                                   &error_msg);
+    dex_file = dex_file_loader.Open(raw_dex_file,
+                                    header->file_size_,
+                                    location,
+                                    oat_dex_file->dex_file_location_checksum_,
+                                    nullptr,
+                                    /* verify */ false,
+                                    /* verify_checksum */ false,
+                                    &error_msg);
   }
   if (dex_file == nullptr) {
     LOG(ERROR) << "Failed to open dex file for layout: " << error_msg;
@@ -3653,6 +3655,7 @@
                << " error: " << error_msg;
     return false;
   }
+  const ArtDexFileLoader dex_file_loader;
   std::vector<std::unique_ptr<const DexFile>> dex_files;
   for (OatDexFile& oat_dex_file : oat_dex_files_) {
     const uint8_t* raw_dex_file =
@@ -3674,14 +3677,14 @@
     }
 
     // Now, open the dex file.
-    dex_files.emplace_back(DexFileLoader::Open(raw_dex_file,
-                                               oat_dex_file.dex_file_size_,
-                                               oat_dex_file.GetLocation(),
-                                               oat_dex_file.dex_file_location_checksum_,
-                                               /* oat_dex_file */ nullptr,
-                                               verify,
-                                               verify,
-                                               &error_msg));
+    dex_files.emplace_back(dex_file_loader.Open(raw_dex_file,
+                                                oat_dex_file.dex_file_size_,
+                                                oat_dex_file.GetLocation(),
+                                                oat_dex_file.dex_file_location_checksum_,
+                                                /* oat_dex_file */ nullptr,
+                                                verify,
+                                                verify,
+                                                &error_msg));
     if (dex_files.back() == nullptr) {
       LOG(ERROR) << "Failed to open dex file from oat file. File: " << oat_dex_file.GetLocation()
                  << " Error: " << error_msg;
@@ -3689,7 +3692,7 @@
     }
 
     // Set the class_offsets size now that we have easy access to the DexFile and
-    // it has been verified in DexFileLoader::Open.
+    // it has been verified in dex_file_loader.Open.
     oat_dex_file.class_offsets_.resize(dex_files.back()->GetHeader().class_defs_size_);
   }
 
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index 2c98e12..8132323 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -44,6 +44,7 @@
 
 #include "android-base/stringprintf.h"
 
+#include "dex/art_dex_file_loader.h"
 #include "dex/code_item_accessors-no_art-inl.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_exception_helpers.h"
@@ -1879,8 +1880,10 @@
   // all of which are Zip archives with "classes.dex" inside.
   const bool kVerifyChecksum = !gOptions.ignoreBadChecksum;
   std::string error_msg;
+  // TODO: Use DexFileLoader when that is implemented.
+  const ArtDexFileLoader dex_file_loader;
   std::vector<std::unique_ptr<const DexFile>> dex_files;
-  if (!DexFileLoader::Open(
+  if (!dex_file_loader.Open(
         fileName, fileName, /* verify */ true, kVerifyChecksum, &error_msg, &dex_files)) {
     // Display returned error message to user. Note that this error behavior
     // differs from the error messages shown by the original Dalvik dexdump.
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 000d135..a43dd07 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -34,6 +34,7 @@
 #include "android-base/stringprintf.h"
 
 #include "base/logging.h"  // For VLOG_IS_ON.
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_layout.h"
 #include "dex/dex_file_loader.h"
@@ -1923,14 +1924,16 @@
     if (options_.verify_output_) {
       std::string error_msg;
       std::string location = "memory mapped file for " + std::string(file_name);
-      std::unique_ptr<const DexFile> output_dex_file(DexFileLoader::Open(mem_map_->Begin(),
-                                                                         file_size,
-                                                                         location,
-                                                                         /* checksum */ 0,
-                                                                         /*oat_dex_file*/ nullptr,
-                                                                         /*verify*/ true,
-                                                                         /*verify_checksum*/ false,
-                                                                         &error_msg));
+      const ArtDexFileLoader dex_file_loader;
+      std::unique_ptr<const DexFile> output_dex_file(
+          dex_file_loader.Open(mem_map_->Begin(),
+                               file_size,
+                               location,
+                               /* checksum */ 0,
+                               /*oat_dex_file*/ nullptr,
+                               /*verify*/ true,
+                               /*verify_checksum*/ false,
+                               &error_msg));
       CHECK(output_dex_file != nullptr) << "Failed to re-open output file:" << error_msg;
 
       // Do IR-level comparison between input and output. This check ignores potential differences
@@ -1961,8 +1964,9 @@
   // all of which are Zip archives with "classes.dex" inside.
   const bool verify_checksum = !options_.ignore_bad_checksum_;
   std::string error_msg;
+  const ArtDexFileLoader dex_file_loader;
   std::vector<std::unique_ptr<const DexFile>> dex_files;
-  if (!DexFileLoader::Open(
+  if (!dex_file_loader.Open(
         file_name, file_name, /* verify */ true, verify_checksum, &error_msg, &dex_files)) {
     // Display returned error message to user. Note that this error behavior
     // differs from the error messages shown by the original Dalvik dexdump.
diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc
index 5da3b1d..3a7f9ee 100644
--- a/dexlayout/dexlayout_test.cc
+++ b/dexlayout/dexlayout_test.cc
@@ -23,6 +23,7 @@
 
 #include "base/unix_file/fd_file.h"
 #include "common_runtime_test.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/code_item_accessors-inl.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
@@ -318,12 +319,13 @@
   bool MutateDexFile(File* output_dex, const std::string& input_jar, const Mutator& mutator) {
     std::vector<std::unique_ptr<const DexFile>> dex_files;
     std::string error_msg;
-    CHECK(DexFileLoader::Open(input_jar.c_str(),
-                              input_jar.c_str(),
-                              /*verify*/ true,
-                              /*verify_checksum*/ true,
-                              &error_msg,
-                              &dex_files)) << error_msg;
+    const ArtDexFileLoader dex_file_loader;
+    CHECK(dex_file_loader.Open(input_jar.c_str(),
+                               input_jar.c_str(),
+                               /*verify*/ true,
+                               /*verify_checksum*/ true,
+                               &error_msg,
+                               &dex_files)) << error_msg;
     EXPECT_EQ(dex_files.size(), 1u) << "Only one input dex is supported";
     for (const std::unique_ptr<const DexFile>& dex : dex_files) {
       CHECK(dex->EnableWrite()) << "Failed to enable write";
@@ -344,12 +346,13 @@
                      const std::string& dex_location) {
     std::vector<std::unique_ptr<const DexFile>> dex_files;
     std::string error_msg;
-    bool result = DexFileLoader::Open(input_dex.c_str(),
-                                      input_dex,
-                                      /*verify*/ true,
-                                      /*verify_checksum*/ false,
-                                      &error_msg,
-                                      &dex_files);
+    const ArtDexFileLoader dex_file_loader;
+    bool result = dex_file_loader.Open(input_dex.c_str(),
+                                       input_dex,
+                                       /*verify*/ true,
+                                       /*verify_checksum*/ false,
+                                       &error_msg,
+                                       &dex_files);
 
     ASSERT_TRUE(result) << error_msg;
     ASSERT_GE(dex_files.size(), 1u);
diff --git a/dexlist/dexlist.cc b/dexlist/dexlist.cc
index 556938b..e452e98 100644
--- a/dexlist/dexlist.cc
+++ b/dexlist/dexlist.cc
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 
 #include "base/logging.h"  // For InitLogging.
+#include "dex/art_dex_file_loader.h"
 #include "dex/code_item_accessors-no_art-inl.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
@@ -174,7 +175,8 @@
   static constexpr bool kVerifyChecksum = true;
   std::string error_msg;
   std::vector<std::unique_ptr<const DexFile>> dex_files;
-  if (!DexFileLoader::Open(
+  const ArtDexFileLoader dex_file_loader;
+  if (!dex_file_loader.Open(
         fileName, fileName, /* verify */ true, kVerifyChecksum, &error_msg, &dex_files)) {
     fputs(error_msg.c_str(), stderr);
     fputc('\n', stderr);
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index da7d60a..963c6f8 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -30,6 +30,7 @@
  */
 
 #include "fixed_up_dex_file.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
 
@@ -72,7 +73,8 @@
   data.resize(original.Size());
   memcpy(data.data(), original.Begin(), original.Size());
   std::string error;
-  std::unique_ptr<const art::DexFile> new_dex_file(art::DexFileLoader::Open(
+  const art::ArtDexFileLoader dex_file_loader;
+  std::unique_ptr<const art::DexFile> new_dex_file(dex_file_loader.Open(
       data.data(),
       data.size(),
       /*location*/"Unquickening_dexfile.dex",
@@ -103,7 +105,7 @@
     // Overwrite the dex file stored in data with the new result.
     data.clear();
     data.insert(data.end(), mem_map->Begin(), mem_map->Begin() + dex_file_size);
-    new_dex_file = art::DexFileLoader::Open(
+    new_dex_file = dex_file_loader.Open(
         data.data(),
         data.size(),
         /*location*/"Unquickening_dexfile.dex",
diff --git a/openjdkjvmti/ti_class.cc b/openjdkjvmti/ti_class.cc
index f9eb008..b3f5c18 100644
--- a/openjdkjvmti/ti_class.cc
+++ b/openjdkjvmti/ti_class.cc
@@ -42,6 +42,7 @@
 #include "class_linker.h"
 #include "class_table-inl.h"
 #include "common_throws.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file_annotations.h"
 #include "dex/dex_file_loader.h"
 #include "events-inl.h"
@@ -107,12 +108,13 @@
   }
   uint32_t checksum = reinterpret_cast<const art::DexFile::Header*>(map->Begin())->checksum_;
   std::string map_name = map->GetName();
-  std::unique_ptr<const art::DexFile> dex_file(art::DexFileLoader::Open(map_name,
-                                                                        checksum,
-                                                                        std::move(map),
-                                                                        /*verify*/true,
-                                                                        /*verify_checksum*/true,
-                                                                        &error_msg));
+  const art::ArtDexFileLoader dex_file_loader;
+  std::unique_ptr<const art::DexFile> dex_file(dex_file_loader.Open(map_name,
+                                                                    checksum,
+                                                                    std::move(map),
+                                                                    /*verify*/true,
+                                                                    /*verify_checksum*/true,
+                                                                    &error_msg));
   if (dex_file.get() == nullptr) {
     LOG(WARNING) << "Unable to load modified dex file for " << descriptor << ": " << error_msg;
     art::ThrowClassFormatError(nullptr,
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 6194d1e..717b2ba 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -43,6 +43,7 @@
 #include "base/stringpiece.h"
 #include "class_linker-inl.h"
 #include "debugger.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file.h"
 #include "dex/dex_file_loader.h"
 #include "dex/dex_file_types.h"
@@ -426,12 +427,13 @@
     return ERR(INVALID_CLASS_FORMAT);
   }
   uint32_t checksum = reinterpret_cast<const art::DexFile::Header*>(map->Begin())->checksum_;
-  std::unique_ptr<const art::DexFile> dex_file(art::DexFileLoader::Open(map->GetName(),
-                                                                        checksum,
-                                                                        std::move(map),
-                                                                        /*verify*/true,
-                                                                        /*verify_checksum*/true,
-                                                                        error_msg_));
+  const art::ArtDexFileLoader dex_file_loader;
+  std::unique_ptr<const art::DexFile> dex_file(dex_file_loader.Open(map->GetName(),
+                                                                    checksum,
+                                                                    std::move(map),
+                                                                    /*verify*/true,
+                                                                    /*verify_checksum*/true,
+                                                                    error_msg_));
   if (dex_file.get() == nullptr) {
     os << "Unable to load modified dex file for " << def.GetName() << ": " << *error_msg_;
     *error_msg_ = os.str();
diff --git a/openjdkjvmti/ti_search.cc b/openjdkjvmti/ti_search.cc
index 9d5f4ea..cbb7b53 100644
--- a/openjdkjvmti/ti_search.cc
+++ b/openjdkjvmti/ti_search.cc
@@ -38,6 +38,7 @@
 #include "base/enums.h"
 #include "base/macros.h"
 #include "class_linker.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file.h"
 #include "dex/dex_file_loader.h"
 #include "jni_internal.h"
@@ -227,7 +228,8 @@
 
   std::string error_msg;
   std::vector<std::unique_ptr<const art::DexFile>> dex_files;
-  if (!art::DexFileLoader::Open(
+  const art::ArtDexFileLoader dex_file_loader;
+  if (!dex_file_loader.Open(
         segment, segment, /* verify */ true, /* verify_checksum */ true, &error_msg, &dex_files)) {
     LOG(WARNING) << "Could not open " << segment << " for boot classpath extension: " << error_msg;
     return ERR(ILLEGAL_ARGUMENT);
diff --git a/profman/profman.cc b/profman/profman.cc
index c4216fa..9f3e3b6 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -39,6 +39,7 @@
 #include "base/unix_file/fd_file.h"
 #include "boot_image_profile.h"
 #include "bytecode_utils.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/code_item_accessors-inl.h"
 #include "dex/dex_file.h"
 #include "dex/dex_file_loader.h"
@@ -329,25 +330,26 @@
     static constexpr bool kVerifyChecksum = true;
     for (size_t i = 0; i < dex_locations_.size(); ++i) {
       std::string error_msg;
+      const ArtDexFileLoader dex_file_loader;
       std::vector<std::unique_ptr<const DexFile>> dex_files_for_location;
       if (use_apk_fd_list) {
-        if (DexFileLoader::OpenZip(apks_fd_[i],
-                                   dex_locations_[i],
-                                   /* verify */ true,
-                                   kVerifyChecksum,
-                                   &error_msg,
-                                   &dex_files_for_location)) {
+        if (dex_file_loader.OpenZip(apks_fd_[i],
+                                    dex_locations_[i],
+                                    /* verify */ true,
+                                    kVerifyChecksum,
+                                    &error_msg,
+                                    &dex_files_for_location)) {
         } else {
           LOG(WARNING) << "OpenZip failed for '" << dex_locations_[i] << "' " << error_msg;
           continue;
         }
       } else {
-        if (DexFileLoader::Open(apk_files_[i].c_str(),
-                                dex_locations_[i],
-                                /* verify */ true,
-                                kVerifyChecksum,
-                                &error_msg,
-                                &dex_files_for_location)) {
+        if (dex_file_loader.Open(apk_files_[i].c_str(),
+                                 dex_locations_[i],
+                                 /* verify */ true,
+                                 kVerifyChecksum,
+                                 &error_msg,
+                                 &dex_files_for_location)) {
         } else {
           LOG(WARNING) << "Open failed for '" << dex_locations_[i] << "' " << error_msg;
           continue;
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 2657f4f..78cb3b6 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -21,6 +21,70 @@
 JIT_DEBUG_REGISTER_CODE_LDFLAGS = ["-Wl,--keep-unique,__jit_debug_register_code"]
 
 cc_defaults {
+    name: "libdexfile_defaults",
+    defaults: ["art_defaults"],
+    host_supported: true,
+    srcs: [
+        "dex/compact_dex_file.cc",
+        "dex/dex_file.cc",
+        "dex/dex_file_exception_helpers.cc",
+        "dex/dex_file_loader.cc",
+        "dex/dex_file_tracking_registrar.cc",
+        "dex/dex_file_verifier.cc",
+        "dex/dex_instruction.cc",
+        "dex/standard_dex_file.cc",
+        "utf.cc",
+        "utils.cc",
+    ],
+
+    target: {
+        android: {
+            shared_libs: [
+                "libutils",
+            ],
+            static_libs: [
+                "libz",
+                "libbase",
+            ],
+        },
+        host: {
+            shared_libs: [
+                "libz",
+            ],
+        },
+    },
+    generated_sources: ["art_operator_srcs"],
+    // asm_support_gen.h (used by asm_support.h) is generated with cpp-define-generator
+    generated_headers: ["cpp-define-generator-asm-support"],
+    // export our headers so the libart-gtest targets can use it as well.
+    export_generated_headers: ["cpp-define-generator-asm-support"],
+    include_dirs: [
+        "external/icu/icu4c/source/common",
+        "external/zlib",
+    ],
+    shared_libs: [
+        "liblog",
+        // For common macros.
+        "libbase",
+    ],
+    export_include_dirs: ["."],
+    // ART's macros.h depends on libbase's macros.h.
+    // Note: runtime_options.h depends on cmdline. But we don't really want to export this
+    //       generically. dex2oat takes care of it itself.
+    export_shared_lib_headers: ["libbase"],
+}
+
+art_cc_library {
+    name: "libdexfile",
+    defaults: ["libdexfile_defaults"],
+    // Leave the symbols in the shared library so that stack unwinders can
+    // produce meaningful name resolution.
+    strip: {
+        keep_symbols: true,
+    },
+}
+
+cc_defaults {
     name: "libart_defaults",
     defaults: ["art_defaults"],
     host_supported: true,
@@ -62,6 +126,7 @@
         "dex/dex_file_exception_helpers.cc",
         "dex/dex_file_layout.cc",
         "dex/dex_file_loader.cc",
+        "dex/art_dex_file_loader.cc",
         "dex/dex_file_tracking_registrar.cc",
         "dex/dex_file_verifier.cc",
         "dex/dex_instruction.cc",
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index 3ec5335..e646520 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -21,6 +21,7 @@
 #include "base/stl_util.h"
 #include "class_linker.h"
 #include "class_loader_utils.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file.h"
 #include "dex/dex_file_loader.h"
 #include "handle_scope-inl.h"
@@ -203,6 +204,7 @@
   // We may get resource-only apks which we cannot load.
   // TODO(calin): Refine the dex opening interface to be able to tell if an archive contains
   // no dex files. So that we can distinguish the real failures...
+  const ArtDexFileLoader dex_file_loader;
   for (ClassLoaderInfo& info : class_loader_chain_) {
     size_t opened_dex_files_index = info.opened_dex_files.size();
     for (const std::string& cp_elem : info.classpath) {
@@ -215,12 +217,12 @@
       std::string error_msg;
       // When opening the dex files from the context we expect their checksum to match their
       // contents. So pass true to verify_checksum.
-      if (!DexFileLoader::Open(location.c_str(),
-                               location.c_str(),
-                               Runtime::Current()->IsVerificationEnabled(),
-                               /*verify_checksum*/ true,
-                               &error_msg,
-                               &info.opened_dex_files)) {
+      if (!dex_file_loader.Open(location.c_str(),
+                                location.c_str(),
+                                Runtime::Current()->IsVerificationEnabled(),
+                                /*verify_checksum*/ true,
+                                &error_msg,
+                                &info.opened_dex_files)) {
         // If we fail to open the dex file because it's been stripped, try to open the dex file
         // from its corresponding oat file.
         // This could happen when we need to recompile a pre-build whose dex code has been stripped.
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 96d660f..39dbebf 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -35,6 +35,7 @@
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
 #include "compiler_callbacks.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
 #include "gc/heap.h"
@@ -375,7 +376,8 @@
   std::string error_msg;
   MemMap::Init();
   static constexpr bool kVerifyChecksum = true;
-  if (!DexFileLoader::Open(
+  const ArtDexFileLoader dex_file_loader;
+  if (!dex_file_loader.Open(
         location, location, /* verify */ true, kVerifyChecksum, &error_msg, &dex_files)) {
     LOG(FATAL) << "Could not open .dex file '" << location << "': " << error_msg << "\n";
     UNREACHABLE();
@@ -574,12 +576,13 @@
   std::string filename = GetTestDexFileName(name);
   static constexpr bool kVerifyChecksum = true;
   std::string error_msg;
+  const ArtDexFileLoader dex_file_loader;
   std::vector<std::unique_ptr<const DexFile>> dex_files;
-  bool success = DexFileLoader::Open(filename.c_str(),
-                                     filename.c_str(),
-                                     /* verify */ true,
-                                     kVerifyChecksum,
-                                     &error_msg, &dex_files);
+  bool success = dex_file_loader.Open(filename.c_str(),
+                                      filename.c_str(),
+                                      /* verify */ true,
+                                      kVerifyChecksum,
+                                      &error_msg, &dex_files);
   CHECK(success) << "Failed to open '" << filename << "': " << error_msg;
   for (auto& dex_file : dex_files) {
     CHECK_EQ(PROT_READ, dex_file->GetPermissions());
diff --git a/runtime/dex/art_dex_file_loader.cc b/runtime/dex/art_dex_file_loader.cc
new file mode 100644
index 0000000..282b282
--- /dev/null
+++ b/runtime/dex/art_dex_file_loader.cc
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "art_dex_file_loader.h"
+
+#include <sys/mman.h>  // For the PROT_* and MAP_* constants.
+#include <sys/stat.h>
+
+#include "android-base/stringprintf.h"
+
+#include "base/file_magic.h"
+#include "base/stl_util.h"
+#include "base/systrace.h"
+#include "base/unix_file/fd_file.h"
+#include "compact_dex_file.h"
+#include "dex_file.h"
+#include "dex_file_verifier.h"
+#include "standard_dex_file.h"
+#include "zip_archive.h"
+
+namespace art {
+
+namespace {
+
+class MemMapContainer : public DexFileContainer {
+ public:
+  explicit MemMapContainer(std::unique_ptr<MemMap>&& mem_map) : mem_map_(std::move(mem_map)) { }
+  virtual ~MemMapContainer() OVERRIDE { }
+
+  int GetPermissions() OVERRIDE {
+    if (mem_map_.get() == nullptr) {
+      return 0;
+    } else {
+      return mem_map_->GetProtect();
+    }
+  }
+
+  bool IsReadOnly() OVERRIDE {
+    return GetPermissions() == PROT_READ;
+  }
+
+  bool EnableWrite() OVERRIDE {
+    CHECK(IsReadOnly());
+    if (mem_map_.get() == nullptr) {
+      return false;
+    } else {
+      return mem_map_->Protect(PROT_READ | PROT_WRITE);
+    }
+  }
+
+  bool DisableWrite() OVERRIDE {
+    CHECK(!IsReadOnly());
+    if (mem_map_.get() == nullptr) {
+      return false;
+    } else {
+      return mem_map_->Protect(PROT_READ);
+    }
+  }
+
+ private:
+  std::unique_ptr<MemMap> mem_map_;
+  DISALLOW_COPY_AND_ASSIGN(MemMapContainer);
+};
+
+}  // namespace
+
+using android::base::StringPrintf;
+
+static constexpr OatDexFile* kNoOatDexFile = nullptr;
+
+
+bool ArtDexFileLoader::GetMultiDexChecksums(const char* filename,
+                                            std::vector<uint32_t>* checksums,
+                                            std::string* error_msg,
+                                            int zip_fd) const {
+  CHECK(checksums != nullptr);
+  uint32_t magic;
+
+  File fd;
+  if (zip_fd != -1) {
+     if (ReadMagicAndReset(zip_fd, &magic, error_msg)) {
+       fd = File(zip_fd, false /* check_usage */);
+     }
+  } else {
+    fd = OpenAndReadMagic(filename, &magic, error_msg);
+  }
+  if (fd.Fd() == -1) {
+    DCHECK(!error_msg->empty());
+    return false;
+  }
+  if (IsZipMagic(magic)) {
+    std::unique_ptr<ZipArchive> zip_archive(
+        ZipArchive::OpenFromFd(fd.Release(), filename, error_msg));
+    if (zip_archive.get() == nullptr) {
+      *error_msg = StringPrintf("Failed to open zip archive '%s' (error msg: %s)", filename,
+                                error_msg->c_str());
+      return false;
+    }
+
+    uint32_t i = 0;
+    std::string zip_entry_name = GetMultiDexClassesDexName(i++);
+    std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(zip_entry_name.c_str(), error_msg));
+    if (zip_entry.get() == nullptr) {
+      *error_msg = StringPrintf("Zip archive '%s' doesn't contain %s (error msg: %s)", filename,
+          zip_entry_name.c_str(), error_msg->c_str());
+      return false;
+    }
+
+    do {
+      checksums->push_back(zip_entry->GetCrc32());
+      zip_entry_name = GetMultiDexClassesDexName(i++);
+      zip_entry.reset(zip_archive->Find(zip_entry_name.c_str(), error_msg));
+    } while (zip_entry.get() != nullptr);
+    return true;
+  }
+  if (IsMagicValid(magic)) {
+    std::unique_ptr<const DexFile> dex_file(
+        OpenFile(fd.Release(), filename, false, false, error_msg));
+    if (dex_file == nullptr) {
+      return false;
+    }
+    checksums->push_back(dex_file->GetHeader().checksum_);
+    return true;
+  }
+  *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename);
+  return false;
+}
+
+std::unique_ptr<const DexFile> ArtDexFileLoader::Open(const uint8_t* base,
+                                                      size_t size,
+                                                      const std::string& location,
+                                                      uint32_t location_checksum,
+                                                      const OatDexFile* oat_dex_file,
+                                                      bool verify,
+                                                      bool verify_checksum,
+                                                      std::string* error_msg) const {
+  ScopedTrace trace(std::string("Open dex file from RAM ") + location);
+  return OpenCommon(base,
+                    size,
+                    location,
+                    location_checksum,
+                    oat_dex_file,
+                    verify,
+                    verify_checksum,
+                    error_msg,
+                    /*container*/ nullptr,
+                    /*verify_result*/ nullptr);
+}
+
+std::unique_ptr<const DexFile> ArtDexFileLoader::Open(const std::string& location,
+                                                      uint32_t location_checksum,
+                                                      std::unique_ptr<MemMap> map,
+                                                      bool verify,
+                                                      bool verify_checksum,
+                                                      std::string* error_msg) const {
+  ScopedTrace trace(std::string("Open dex file from mapped-memory ") + location);
+  CHECK(map.get() != nullptr);
+
+  if (map->Size() < sizeof(DexFile::Header)) {
+    *error_msg = StringPrintf(
+        "DexFile: failed to open dex file '%s' that is too short to have a header",
+        location.c_str());
+    return nullptr;
+  }
+
+  std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
+                                                 map->Size(),
+                                                 location,
+                                                 location_checksum,
+                                                 kNoOatDexFile,
+                                                 verify,
+                                                 verify_checksum,
+                                                 error_msg,
+                                                 new MemMapContainer(std::move(map)),
+                                                 /*verify_result*/ nullptr);
+  return dex_file;
+}
+
+bool ArtDexFileLoader::Open(const char* filename,
+                            const std::string& location,
+                            bool verify,
+                            bool verify_checksum,
+                            std::string* error_msg,
+                            std::vector<std::unique_ptr<const DexFile>>* dex_files) const {
+  ScopedTrace trace(std::string("Open dex file ") + std::string(location));
+  DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is nullptr";
+  uint32_t magic;
+  File fd = OpenAndReadMagic(filename, &magic, error_msg);
+  if (fd.Fd() == -1) {
+    DCHECK(!error_msg->empty());
+    return false;
+  }
+  if (IsZipMagic(magic)) {
+    return OpenZip(fd.Release(), location, verify, verify_checksum, error_msg, dex_files);
+  }
+  if (IsMagicValid(magic)) {
+    std::unique_ptr<const DexFile> dex_file(OpenFile(fd.Release(),
+                                                     location,
+                                                     verify,
+                                                     verify_checksum,
+                                                     error_msg));
+    if (dex_file.get() != nullptr) {
+      dex_files->push_back(std::move(dex_file));
+      return true;
+    } else {
+      return false;
+    }
+  }
+  *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename);
+  return false;
+}
+
+std::unique_ptr<const DexFile> ArtDexFileLoader::OpenDex(int fd,
+                                                         const std::string& location,
+                                                         bool verify,
+                                                         bool verify_checksum,
+                                                         std::string* error_msg) const {
+  ScopedTrace trace("Open dex file " + std::string(location));
+  return OpenFile(fd, location, verify, verify_checksum, error_msg);
+}
+
+bool ArtDexFileLoader::OpenZip(int fd,
+                               const std::string& location,
+                               bool verify,
+                               bool verify_checksum,
+                               std::string* error_msg,
+                               std::vector<std::unique_ptr<const DexFile>>* dex_files) const {
+  ScopedTrace trace("Dex file open Zip " + std::string(location));
+  DCHECK(dex_files != nullptr) << "DexFile::OpenZip: out-param is nullptr";
+  std::unique_ptr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(fd, location.c_str(), error_msg));
+  if (zip_archive.get() == nullptr) {
+    DCHECK(!error_msg->empty());
+    return false;
+  }
+  return OpenAllDexFilesFromZip(
+      *zip_archive, location, verify, verify_checksum, error_msg, dex_files);
+}
+
+std::unique_ptr<const DexFile> ArtDexFileLoader::OpenFile(int fd,
+                                                          const std::string& location,
+                                                          bool verify,
+                                                          bool verify_checksum,
+                                                          std::string* error_msg) const {
+  ScopedTrace trace(std::string("Open dex file ") + std::string(location));
+  CHECK(!location.empty());
+  std::unique_ptr<MemMap> map;
+  {
+    File delayed_close(fd, /* check_usage */ false);
+    struct stat sbuf;
+    memset(&sbuf, 0, sizeof(sbuf));
+    if (fstat(fd, &sbuf) == -1) {
+      *error_msg = StringPrintf("DexFile: fstat '%s' failed: %s", location.c_str(),
+                                strerror(errno));
+      return nullptr;
+    }
+    if (S_ISDIR(sbuf.st_mode)) {
+      *error_msg = StringPrintf("Attempt to mmap directory '%s'", location.c_str());
+      return nullptr;
+    }
+    size_t length = sbuf.st_size;
+    map.reset(MemMap::MapFile(length,
+                              PROT_READ,
+                              MAP_PRIVATE,
+                              fd,
+                              0,
+                              /*low_4gb*/false,
+                              location.c_str(),
+                              error_msg));
+    if (map == nullptr) {
+      DCHECK(!error_msg->empty());
+      return nullptr;
+    }
+  }
+
+  if (map->Size() < sizeof(DexFile::Header)) {
+    *error_msg = StringPrintf(
+        "DexFile: failed to open dex file '%s' that is too short to have a header",
+        location.c_str());
+    return nullptr;
+  }
+
+  const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(map->Begin());
+
+  std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
+                                                 map->Size(),
+                                                 location,
+                                                 dex_header->checksum_,
+                                                 kNoOatDexFile,
+                                                 verify,
+                                                 verify_checksum,
+                                                 error_msg,
+                                                 new MemMapContainer(std::move(map)),
+                                                 /*verify_result*/ nullptr);
+
+  return dex_file;
+}
+
+std::unique_ptr<const DexFile> ArtDexFileLoader::OpenOneDexFileFromZip(
+    const ZipArchive& zip_archive,
+    const char* entry_name,
+    const std::string& location,
+    bool verify,
+    bool verify_checksum,
+    std::string* error_msg,
+    ZipOpenErrorCode* error_code) const {
+  ScopedTrace trace("Dex file open from Zip Archive " + std::string(location));
+  CHECK(!location.empty());
+  std::unique_ptr<ZipEntry> zip_entry(zip_archive.Find(entry_name, error_msg));
+  if (zip_entry == nullptr) {
+    *error_code = ZipOpenErrorCode::kEntryNotFound;
+    return nullptr;
+  }
+  if (zip_entry->GetUncompressedLength() == 0) {
+    *error_msg = StringPrintf("Dex file '%s' has zero length", location.c_str());
+    *error_code = ZipOpenErrorCode::kDexFileError;
+    return nullptr;
+  }
+
+  std::unique_ptr<MemMap> map;
+  if (zip_entry->IsUncompressed()) {
+    if (!zip_entry->IsAlignedTo(alignof(DexFile::Header))) {
+      // Do not mmap unaligned ZIP entries because
+      // doing so would fail dex verification which requires 4 byte alignment.
+      LOG(WARNING) << "Can't mmap dex file " << location << "!" << entry_name << " directly; "
+                   << "please zipalign to " << alignof(DexFile::Header) << " bytes. "
+                   << "Falling back to extracting file.";
+    } else {
+      // Map uncompressed files within zip as file-backed to avoid a dirty copy.
+      map.reset(zip_entry->MapDirectlyFromFile(location.c_str(), /*out*/error_msg));
+      if (map == nullptr) {
+        LOG(WARNING) << "Can't mmap dex file " << location << "!" << entry_name << " directly; "
+                     << "is your ZIP file corrupted? Falling back to extraction.";
+        // Try again with Extraction which still has a chance of recovery.
+      }
+    }
+  }
+
+  if (map == nullptr) {
+    // Default path for compressed ZIP entries,
+    // and fallback for stored ZIP entries.
+    map.reset(zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg));
+  }
+
+  if (map == nullptr) {
+    *error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", entry_name, location.c_str(),
+                              error_msg->c_str());
+    *error_code = ZipOpenErrorCode::kExtractToMemoryError;
+    return nullptr;
+  }
+  VerifyResult verify_result;
+  std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
+                                                 map->Size(),
+                                                 location,
+                                                 zip_entry->GetCrc32(),
+                                                 kNoOatDexFile,
+                                                 verify,
+                                                 verify_checksum,
+                                                 error_msg,
+                                                 new MemMapContainer(std::move(map)),
+                                                 &verify_result);
+  if (dex_file == nullptr) {
+    if (verify_result == VerifyResult::kVerifyNotAttempted) {
+      *error_code = ZipOpenErrorCode::kDexFileError;
+    } else {
+      *error_code = ZipOpenErrorCode::kVerifyError;
+    }
+    return nullptr;
+  }
+  if (!dex_file->DisableWrite()) {
+    *error_msg = StringPrintf("Failed to make dex file '%s' read only", location.c_str());
+    *error_code = ZipOpenErrorCode::kMakeReadOnlyError;
+    return nullptr;
+  }
+  CHECK(dex_file->IsReadOnly()) << location;
+  if (verify_result != VerifyResult::kVerifySucceeded) {
+    *error_code = ZipOpenErrorCode::kVerifyError;
+    return nullptr;
+  }
+  *error_code = ZipOpenErrorCode::kNoError;
+  return dex_file;
+}
+
+// Technically we do not have a limitation with respect to the number of dex files that can be in a
+// multidex APK. However, it's bad practice, as each dex file requires its own tables for symbols
+// (types, classes, methods, ...) and dex caches. So warn the user that we open a zip with what
+// seems an excessive number.
+static constexpr size_t kWarnOnManyDexFilesThreshold = 100;
+
+bool ArtDexFileLoader::OpenAllDexFilesFromZip(
+    const ZipArchive& zip_archive,
+    const std::string& location,
+    bool verify,
+    bool verify_checksum,
+    std::string* error_msg,
+    std::vector<std::unique_ptr<const DexFile>>* dex_files) const {
+  ScopedTrace trace("Dex file open from Zip " + std::string(location));
+  DCHECK(dex_files != nullptr) << "DexFile::OpenFromZip: out-param is nullptr";
+  ZipOpenErrorCode error_code;
+  std::unique_ptr<const DexFile> dex_file(OpenOneDexFileFromZip(zip_archive,
+                                                                kClassesDex,
+                                                                location,
+                                                                verify,
+                                                                verify_checksum,
+                                                                error_msg,
+                                                                &error_code));
+  if (dex_file.get() == nullptr) {
+    return false;
+  } else {
+    // Had at least classes.dex.
+    dex_files->push_back(std::move(dex_file));
+
+    // Now try some more.
+
+    // We could try to avoid std::string allocations by working on a char array directly. As we
+    // do not expect a lot of iterations, this seems too involved and brittle.
+
+    for (size_t i = 1; ; ++i) {
+      std::string name = GetMultiDexClassesDexName(i);
+      std::string fake_location = GetMultiDexLocation(i, location.c_str());
+      std::unique_ptr<const DexFile> next_dex_file(OpenOneDexFileFromZip(zip_archive,
+                                                                         name.c_str(),
+                                                                         fake_location,
+                                                                         verify,
+                                                                         verify_checksum,
+                                                                         error_msg,
+                                                                         &error_code));
+      if (next_dex_file.get() == nullptr) {
+        if (error_code != ZipOpenErrorCode::kEntryNotFound) {
+          LOG(WARNING) << "Zip open failed: " << *error_msg;
+        }
+        break;
+      } else {
+        dex_files->push_back(std::move(next_dex_file));
+      }
+
+      if (i == kWarnOnManyDexFilesThreshold) {
+        LOG(WARNING) << location << " has in excess of " << kWarnOnManyDexFilesThreshold
+                     << " dex files. Please consider coalescing and shrinking the number to "
+                        " avoid runtime overhead.";
+      }
+
+      if (i == std::numeric_limits<size_t>::max()) {
+        LOG(ERROR) << "Overflow in number of dex files!";
+        break;
+      }
+    }
+
+    return true;
+  }
+}
+
+}  // namespace art
diff --git a/runtime/dex/art_dex_file_loader.h b/runtime/dex/art_dex_file_loader.h
new file mode 100644
index 0000000..a6191d9
--- /dev/null
+++ b/runtime/dex/art_dex_file_loader.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_DEX_ART_DEX_FILE_LOADER_H_
+#define ART_RUNTIME_DEX_ART_DEX_FILE_LOADER_H_
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "dex_file_loader.h"
+#include "base/macros.h"
+
+namespace art {
+
+class DexFile;
+class DexFileContainer;
+class MemMap;
+class OatDexFile;
+class ZipArchive;
+
+// Class that is used to open dex files and deal with corresponding multidex and location logic.
+class ArtDexFileLoader : public DexFileLoader {
+ public:
+  virtual ~ArtDexFileLoader() { }
+
+  // Returns the checksums of a file for comparison with GetLocationChecksum().
+  // For .dex files, this is the single header checksum.
+  // For zip files, this is the zip entry CRC32 checksum for classes.dex and
+  // each additional multidex entry classes2.dex, classes3.dex, etc.
+  // If a valid zip_fd is provided the file content will be read directly from
+  // the descriptor and `filename` will be used as alias for error logging. If
+  // zip_fd is -1, the method will try to open the `filename` and read the
+  // content from it.
+  // Return true if the checksums could be found, false otherwise.
+  bool GetMultiDexChecksums(const char* filename,
+                            std::vector<uint32_t>* checksums,
+                            std::string* error_msg,
+                            int zip_fd = -1) const OVERRIDE;
+
+  // Opens .dex file, backed by existing memory
+  std::unique_ptr<const DexFile> Open(const uint8_t* base,
+                                      size_t size,
+                                      const std::string& location,
+                                      uint32_t location_checksum,
+                                      const OatDexFile* oat_dex_file,
+                                      bool verify,
+                                      bool verify_checksum,
+                                      std::string* error_msg) const OVERRIDE;
+
+  // Opens .dex file that has been memory-mapped by the caller.
+  std::unique_ptr<const DexFile> Open(const std::string& location,
+                                      uint32_t location_checkum,
+                                      std::unique_ptr<MemMap> mem_map,
+                                      bool verify,
+                                      bool verify_checksum,
+                                      std::string* error_msg) const OVERRIDE;
+
+  // Opens all .dex files found in the file, guessing the container format based on file extension.
+  bool Open(const char* filename,
+            const std::string& location,
+            bool verify,
+            bool verify_checksum,
+            std::string* error_msg,
+            std::vector<std::unique_ptr<const DexFile>>* dex_files) const OVERRIDE;
+
+  // Open a single dex file from an fd. This function closes the fd.
+  std::unique_ptr<const DexFile> OpenDex(int fd,
+                                         const std::string& location,
+                                         bool verify,
+                                         bool verify_checksum,
+                                         std::string* error_msg) const OVERRIDE;
+
+  // Opens dex files from within a .jar, .zip, or .apk file
+  bool OpenZip(int fd,
+               const std::string& location,
+               bool verify,
+               bool verify_checksum,
+               std::string* error_msg,
+               std::vector<std::unique_ptr<const DexFile>>* dex_files) const OVERRIDE;
+
+ private:
+  std::unique_ptr<const DexFile> OpenFile(int fd,
+                                          const std::string& location,
+                                          bool verify,
+                                          bool verify_checksum,
+                                          std::string* error_msg) const OVERRIDE;
+
+  // Open all classesXXX.dex files from a zip archive.
+  bool OpenAllDexFilesFromZip(const ZipArchive& zip_archive,
+                              const std::string& location,
+                              bool verify,
+                              bool verify_checksum,
+                              std::string* error_msg,
+                              std::vector<std::unique_ptr<const DexFile>>* dex_files)
+      const OVERRIDE;
+
+  // Opens .dex file from the entry_name in a zip archive. error_code is undefined when non-null
+  // return.
+  std::unique_ptr<const DexFile> OpenOneDexFileFromZip(const ZipArchive& zip_archive,
+                                                       const char* entry_name,
+                                                       const std::string& location,
+                                                       bool verify,
+                                                       bool verify_checksum,
+                                                       std::string* error_msg,
+                                                       ZipOpenErrorCode* error_code) const OVERRIDE;
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_DEX_ART_DEX_FILE_LOADER_H_
diff --git a/runtime/dex/code_item_accessors_test.cc b/runtime/dex/code_item_accessors_test.cc
index b29d10b..2e21956 100644
--- a/runtime/dex/code_item_accessors_test.cc
+++ b/runtime/dex/code_item_accessors_test.cc
@@ -19,6 +19,7 @@
 #include <memory>
 
 #include "common_runtime_test.h"
+#include "art_dex_file_loader.h"
 #include "dex_file_loader.h"
 #include "mem_map.h"
 
@@ -44,13 +45,13 @@
     StandardDexFile::WriteMagic(map->Begin());
     StandardDexFile::WriteCurrentVersion(map->Begin());
   }
-  std::unique_ptr<const DexFile> dex(
-      DexFileLoader::Open("location",
-                          /*location_checksum*/ 123,
-                          std::move(map),
-                          /*verify*/false,
-                          /*verify_checksum*/false,
-                          &error_msg));
+  const ArtDexFileLoader dex_file_loader;
+  std::unique_ptr<const DexFile> dex(dex_file_loader.Open("location",
+                                                          /*location_checksum*/ 123,
+                                                          std::move(map),
+                                                          /*verify*/false,
+                                                          /*verify_checksum*/false,
+                                                          &error_msg));
   CHECK(dex != nullptr) << error_msg;
   return dex;
 }
diff --git a/runtime/dex/dex_file_loader.cc b/runtime/dex/dex_file_loader.cc
index fafd698..10aef56 100644
--- a/runtime/dex/dex_file_loader.cc
+++ b/runtime/dex/dex_file_loader.cc
@@ -16,72 +16,25 @@
 
 #include "dex_file_loader.h"
 
-#include <sys/mman.h>  // For the PROT_* and MAP_* constants.
-#include <sys/stat.h>
+// #include <sys/mman.h>  // For the PROT_* and MAP_* constants.
+// #include <sys/stat.h>
 
 #include "android-base/stringprintf.h"
 
 #include "base/file_magic.h"
 #include "base/stl_util.h"
-#include "base/systrace.h"
-#include "base/unix_file/fd_file.h"
+// #include "base/systrace.h"
+// #include "base/unix_file/fd_file.h"
 #include "compact_dex_file.h"
 #include "dex_file.h"
 #include "dex_file_verifier.h"
 #include "standard_dex_file.h"
-#include "zip_archive.h"
+// #include "zip_archive.h"
 
 namespace art {
 
-namespace {
-
-class MemMapContainer : public DexFileContainer {
- public:
-  explicit MemMapContainer(std::unique_ptr<MemMap>&& mem_map) : mem_map_(std::move(mem_map)) { }
-  virtual ~MemMapContainer() OVERRIDE { }
-
-  int GetPermissions() OVERRIDE {
-    if (mem_map_.get() == nullptr) {
-      return 0;
-    } else {
-      return mem_map_->GetProtect();
-    }
-  }
-
-  bool IsReadOnly() OVERRIDE {
-    return GetPermissions() == PROT_READ;
-  }
-
-  bool EnableWrite() OVERRIDE {
-    CHECK(IsReadOnly());
-    if (mem_map_.get() == nullptr) {
-      return false;
-    } else {
-      return mem_map_->Protect(PROT_READ | PROT_WRITE);
-    }
-  }
-
-  bool DisableWrite() OVERRIDE {
-    CHECK(!IsReadOnly());
-    if (mem_map_.get() == nullptr) {
-      return false;
-    } else {
-      return mem_map_->Protect(PROT_READ);
-    }
-  }
-
- private:
-  std::unique_ptr<MemMap> mem_map_;
-  DISALLOW_COPY_AND_ASSIGN(MemMapContainer);
-};
-
-}  // namespace
-
 using android::base::StringPrintf;
 
-static constexpr OatDexFile* kNoOatDexFile = nullptr;
-
-
 bool DexFileLoader::IsMagicValid(uint32_t magic) {
   return IsMagicValid(reinterpret_cast<uint8_t*>(&magic));
 }
@@ -101,63 +54,6 @@
   return false;
 }
 
-bool DexFileLoader::GetMultiDexChecksums(const char* filename,
-                                         std::vector<uint32_t>* checksums,
-                                         std::string* error_msg,
-                                         int zip_fd) {
-  CHECK(checksums != nullptr);
-  uint32_t magic;
-
-  File fd;
-  if (zip_fd != -1) {
-     if (ReadMagicAndReset(zip_fd, &magic, error_msg)) {
-       fd = File(zip_fd, false /* check_usage */);
-     }
-  } else {
-    fd = OpenAndReadMagic(filename, &magic, error_msg);
-  }
-  if (fd.Fd() == -1) {
-    DCHECK(!error_msg->empty());
-    return false;
-  }
-  if (IsZipMagic(magic)) {
-    std::unique_ptr<ZipArchive> zip_archive(
-        ZipArchive::OpenFromFd(fd.Release(), filename, error_msg));
-    if (zip_archive.get() == nullptr) {
-      *error_msg = StringPrintf("Failed to open zip archive '%s' (error msg: %s)", filename,
-                                error_msg->c_str());
-      return false;
-    }
-
-    uint32_t i = 0;
-    std::string zip_entry_name = GetMultiDexClassesDexName(i++);
-    std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(zip_entry_name.c_str(), error_msg));
-    if (zip_entry.get() == nullptr) {
-      *error_msg = StringPrintf("Zip archive '%s' doesn't contain %s (error msg: %s)", filename,
-          zip_entry_name.c_str(), error_msg->c_str());
-      return false;
-    }
-
-    do {
-      checksums->push_back(zip_entry->GetCrc32());
-      zip_entry_name = GetMultiDexClassesDexName(i++);
-      zip_entry.reset(zip_archive->Find(zip_entry_name.c_str(), error_msg));
-    } while (zip_entry.get() != nullptr);
-    return true;
-  }
-  if (IsMagicValid(magic)) {
-    std::unique_ptr<const DexFile> dex_file(
-        OpenFile(fd.Release(), filename, false, false, error_msg));
-    if (dex_file == nullptr) {
-      return false;
-    }
-    checksums->push_back(dex_file->GetHeader().checksum_);
-    return true;
-  }
-  *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename);
-  return false;
-}
-
 bool DexFileLoader::IsMultiDexLocation(const char* location) {
   return strrchr(location, kMultiDexSeparator) != nullptr;
 }
@@ -187,326 +83,102 @@
   }
 }
 
-std::unique_ptr<const DexFile> DexFileLoader::Open(const uint8_t* base,
-                                                   size_t size,
-                                                   const std::string& location,
-                                                   uint32_t location_checksum,
-                                                   const OatDexFile* oat_dex_file,
-                                                   bool verify,
-                                                   bool verify_checksum,
-                                                   std::string* error_msg) {
-  ScopedTrace trace(std::string("Open dex file from RAM ") + location);
-  return OpenCommon(base,
-                    size,
-                    location,
-                    location_checksum,
-                    oat_dex_file,
-                    verify,
-                    verify_checksum,
-                    error_msg,
-                    /*container*/ nullptr,
-                    /*verify_result*/ nullptr);
-}
+// All of the implementations here should be independent of the runtime.
+// TODO: implement all the virtual methods.
 
-std::unique_ptr<const DexFile> DexFileLoader::Open(const std::string& location,
-                                                   uint32_t location_checksum,
-                                                   std::unique_ptr<MemMap> map,
-                                                   bool verify,
-                                                   bool verify_checksum,
-                                                   std::string* error_msg) {
-  ScopedTrace trace(std::string("Open dex file from mapped-memory ") + location);
-  CHECK(map.get() != nullptr);
-
-  if (map->Size() < sizeof(DexFile::Header)) {
-    *error_msg = StringPrintf(
-        "DexFile: failed to open dex file '%s' that is too short to have a header",
-        location.c_str());
-    return nullptr;
-  }
-
-  std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
-                                                 map->Size(),
-                                                 location,
-                                                 location_checksum,
-                                                 kNoOatDexFile,
-                                                 verify,
-                                                 verify_checksum,
-                                                 error_msg,
-                                                 new MemMapContainer(std::move(map)),
-                                                 /*verify_result*/ nullptr);
-  return dex_file;
-}
-
-bool DexFileLoader::Open(const char* filename,
-                         const std::string& location,
-                         bool verify,
-                         bool verify_checksum,
-                         std::string* error_msg,
-                         std::vector<std::unique_ptr<const DexFile>>* dex_files) {
-  ScopedTrace trace(std::string("Open dex file ") + std::string(location));
-  DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is nullptr";
-  uint32_t magic;
-  File fd = OpenAndReadMagic(filename, &magic, error_msg);
-  if (fd.Fd() == -1) {
-    DCHECK(!error_msg->empty());
-    return false;
-  }
-  if (IsZipMagic(magic)) {
-    return OpenZip(fd.Release(), location, verify, verify_checksum, error_msg, dex_files);
-  }
-  if (IsMagicValid(magic)) {
-    std::unique_ptr<const DexFile> dex_file(OpenFile(fd.Release(),
-                                                     location,
-                                                     verify,
-                                                     verify_checksum,
-                                                     error_msg));
-    if (dex_file.get() != nullptr) {
-      dex_files->push_back(std::move(dex_file));
-      return true;
-    } else {
-      return false;
-    }
-  }
-  *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename);
+bool DexFileLoader::GetMultiDexChecksums(const char* filename ATTRIBUTE_UNUSED,
+                                         std::vector<uint32_t>* checksums ATTRIBUTE_UNUSED,
+                                         std::string* error_msg,
+                                         int zip_fd ATTRIBUTE_UNUSED) const {
+  *error_msg = "UNIMPLEMENTED";
   return false;
 }
 
-std::unique_ptr<const DexFile> DexFileLoader::OpenDex(int fd,
-                                                      const std::string& location,
-                                                      bool verify,
-                                                      bool verify_checksum,
-                                                      std::string* error_msg) {
-  ScopedTrace trace("Open dex file " + std::string(location));
-  return OpenFile(fd, location, verify, verify_checksum, error_msg);
+std::unique_ptr<const DexFile> DexFileLoader::Open(const uint8_t* base ATTRIBUTE_UNUSED,
+                                                   size_t size ATTRIBUTE_UNUSED,
+                                                   const std::string& location ATTRIBUTE_UNUSED,
+                                                   uint32_t location_checksum ATTRIBUTE_UNUSED,
+                                                   const OatDexFile* oat_dex_file ATTRIBUTE_UNUSED,
+                                                   bool verify ATTRIBUTE_UNUSED,
+                                                   bool verify_checksum ATTRIBUTE_UNUSED,
+                                                   std::string* error_msg) const {
+  *error_msg = "UNIMPLEMENTED";
+  return nullptr;
 }
 
-bool DexFileLoader::OpenZip(int fd,
-                            const std::string& location,
-                            bool verify,
-                            bool verify_checksum,
-                            std::string* error_msg,
-                            std::vector<std::unique_ptr<const DexFile>>* dex_files) {
-  ScopedTrace trace("Dex file open Zip " + std::string(location));
-  DCHECK(dex_files != nullptr) << "DexFile::OpenZip: out-param is nullptr";
-  std::unique_ptr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(fd, location.c_str(), error_msg));
-  if (zip_archive.get() == nullptr) {
-    DCHECK(!error_msg->empty());
-    return false;
-  }
-  return OpenAllDexFilesFromZip(
-      *zip_archive, location, verify, verify_checksum, error_msg, dex_files);
+std::unique_ptr<const DexFile> DexFileLoader::Open(const std::string& location ATTRIBUTE_UNUSED,
+                                                   uint32_t location_checksum ATTRIBUTE_UNUSED,
+                                                   std::unique_ptr<MemMap> map ATTRIBUTE_UNUSED,
+                                                   bool verify ATTRIBUTE_UNUSED,
+                                                   bool verify_checksum ATTRIBUTE_UNUSED,
+                                                   std::string* error_msg) const {
+  *error_msg = "UNIMPLEMENTED";
+  return nullptr;
 }
 
-std::unique_ptr<const DexFile> DexFileLoader::OpenFile(int fd,
-                                                       const std::string& location,
-                                                       bool verify,
-                                                       bool verify_checksum,
-                                                       std::string* error_msg) {
-  ScopedTrace trace(std::string("Open dex file ") + std::string(location));
-  CHECK(!location.empty());
-  std::unique_ptr<MemMap> map;
-  {
-    File delayed_close(fd, /* check_usage */ false);
-    struct stat sbuf;
-    memset(&sbuf, 0, sizeof(sbuf));
-    if (fstat(fd, &sbuf) == -1) {
-      *error_msg = StringPrintf("DexFile: fstat '%s' failed: %s", location.c_str(),
-                                strerror(errno));
-      return nullptr;
-    }
-    if (S_ISDIR(sbuf.st_mode)) {
-      *error_msg = StringPrintf("Attempt to mmap directory '%s'", location.c_str());
-      return nullptr;
-    }
-    size_t length = sbuf.st_size;
-    map.reset(MemMap::MapFile(length,
-                              PROT_READ,
-                              MAP_PRIVATE,
-                              fd,
-                              0,
-                              /*low_4gb*/false,
-                              location.c_str(),
-                              error_msg));
-    if (map == nullptr) {
-      DCHECK(!error_msg->empty());
-      return nullptr;
-    }
-  }
+bool DexFileLoader::Open(
+    const char* filename ATTRIBUTE_UNUSED,
+    const std::string& location ATTRIBUTE_UNUSED,
+    bool verify ATTRIBUTE_UNUSED,
+    bool verify_checksum ATTRIBUTE_UNUSED,
+    std::string* error_msg,
+    std::vector<std::unique_ptr<const DexFile>>* dex_files ATTRIBUTE_UNUSED) const {
+  *error_msg = "UNIMPLEMENTED";
+  return false;
+}
 
-  if (map->Size() < sizeof(DexFile::Header)) {
-    *error_msg = StringPrintf(
-        "DexFile: failed to open dex file '%s' that is too short to have a header",
-        location.c_str());
-    return nullptr;
-  }
+std::unique_ptr<const DexFile> DexFileLoader::OpenDex(
+    int fd ATTRIBUTE_UNUSED,
+    const std::string& location ATTRIBUTE_UNUSED,
+    bool verify ATTRIBUTE_UNUSED,
+    bool verify_checksum ATTRIBUTE_UNUSED,
+    std::string* error_msg) const {
+  *error_msg = "UNIMPLEMENTED";
+  return nullptr;
+}
 
-  const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(map->Begin());
+bool DexFileLoader::OpenZip(
+    int fd ATTRIBUTE_UNUSED,
+    const std::string& location ATTRIBUTE_UNUSED,
+    bool verify ATTRIBUTE_UNUSED,
+    bool verify_checksum ATTRIBUTE_UNUSED,
+    std::string* error_msg,
+    std::vector<std::unique_ptr<const DexFile>>* dex_files ATTRIBUTE_UNUSED) const {
+  *error_msg = "UNIMPLEMENTED";
+  return false;
+}
 
-  std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
-                                                 map->Size(),
-                                                 location,
-                                                 dex_header->checksum_,
-                                                 kNoOatDexFile,
-                                                 verify,
-                                                 verify_checksum,
-                                                 error_msg,
-                                                 new MemMapContainer(std::move(map)),
-                                                 /*verify_result*/ nullptr);
-
-  return dex_file;
+std::unique_ptr<const DexFile> DexFileLoader::OpenFile(
+    int fd ATTRIBUTE_UNUSED,
+    const std::string& location ATTRIBUTE_UNUSED,
+    bool verify ATTRIBUTE_UNUSED,
+    bool verify_checksum ATTRIBUTE_UNUSED,
+    std::string* error_msg) const {
+  *error_msg = "UNIMPLEMENTED";
+  return nullptr;
 }
 
 std::unique_ptr<const DexFile> DexFileLoader::OpenOneDexFileFromZip(
-    const ZipArchive& zip_archive,
-    const char* entry_name,
-    const std::string& location,
-    bool verify,
-    bool verify_checksum,
+    const ZipArchive& zip_archive ATTRIBUTE_UNUSED,
+    const char* entry_name ATTRIBUTE_UNUSED,
+    const std::string& location ATTRIBUTE_UNUSED,
+    bool verify ATTRIBUTE_UNUSED,
+    bool verify_checksum ATTRIBUTE_UNUSED,
     std::string* error_msg,
-    ZipOpenErrorCode* error_code) {
-  ScopedTrace trace("Dex file open from Zip Archive " + std::string(location));
-  CHECK(!location.empty());
-  std::unique_ptr<ZipEntry> zip_entry(zip_archive.Find(entry_name, error_msg));
-  if (zip_entry == nullptr) {
-    *error_code = ZipOpenErrorCode::kEntryNotFound;
-    return nullptr;
-  }
-  if (zip_entry->GetUncompressedLength() == 0) {
-    *error_msg = StringPrintf("Dex file '%s' has zero length", location.c_str());
-    *error_code = ZipOpenErrorCode::kDexFileError;
-    return nullptr;
-  }
-
-  std::unique_ptr<MemMap> map;
-  if (zip_entry->IsUncompressed()) {
-    if (!zip_entry->IsAlignedTo(alignof(DexFile::Header))) {
-      // Do not mmap unaligned ZIP entries because
-      // doing so would fail dex verification which requires 4 byte alignment.
-      LOG(WARNING) << "Can't mmap dex file " << location << "!" << entry_name << " directly; "
-                   << "please zipalign to " << alignof(DexFile::Header) << " bytes. "
-                   << "Falling back to extracting file.";
-    } else {
-      // Map uncompressed files within zip as file-backed to avoid a dirty copy.
-      map.reset(zip_entry->MapDirectlyFromFile(location.c_str(), /*out*/error_msg));
-      if (map == nullptr) {
-        LOG(WARNING) << "Can't mmap dex file " << location << "!" << entry_name << " directly; "
-                     << "is your ZIP file corrupted? Falling back to extraction.";
-        // Try again with Extraction which still has a chance of recovery.
-      }
-    }
-  }
-
-  if (map == nullptr) {
-    // Default path for compressed ZIP entries,
-    // and fallback for stored ZIP entries.
-    map.reset(zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg));
-  }
-
-  if (map == nullptr) {
-    *error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", entry_name, location.c_str(),
-                              error_msg->c_str());
-    *error_code = ZipOpenErrorCode::kExtractToMemoryError;
-    return nullptr;
-  }
-  VerifyResult verify_result;
-  std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
-                                                 map->Size(),
-                                                 location,
-                                                 zip_entry->GetCrc32(),
-                                                 kNoOatDexFile,
-                                                 verify,
-                                                 verify_checksum,
-                                                 error_msg,
-                                                 new MemMapContainer(std::move(map)),
-                                                 &verify_result);
-  if (dex_file == nullptr) {
-    if (verify_result == VerifyResult::kVerifyNotAttempted) {
-      *error_code = ZipOpenErrorCode::kDexFileError;
-    } else {
-      *error_code = ZipOpenErrorCode::kVerifyError;
-    }
-    return nullptr;
-  }
-  if (!dex_file->DisableWrite()) {
-    *error_msg = StringPrintf("Failed to make dex file '%s' read only", location.c_str());
-    *error_code = ZipOpenErrorCode::kMakeReadOnlyError;
-    return nullptr;
-  }
-  CHECK(dex_file->IsReadOnly()) << location;
-  if (verify_result != VerifyResult::kVerifySucceeded) {
-    *error_code = ZipOpenErrorCode::kVerifyError;
-    return nullptr;
-  }
-  *error_code = ZipOpenErrorCode::kNoError;
-  return dex_file;
+    ZipOpenErrorCode* error_code ATTRIBUTE_UNUSED) const {
+  *error_msg = "UNIMPLEMENTED";
+  return nullptr;
 }
 
-// Technically we do not have a limitation with respect to the number of dex files that can be in a
-// multidex APK. However, it's bad practice, as each dex file requires its own tables for symbols
-// (types, classes, methods, ...) and dex caches. So warn the user that we open a zip with what
-// seems an excessive number.
-static constexpr size_t kWarnOnManyDexFilesThreshold = 100;
-
-bool DexFileLoader::OpenAllDexFilesFromZip(const ZipArchive& zip_archive,
-                                           const std::string& location,
-                                           bool verify,
-                                           bool verify_checksum,
-                                           std::string* error_msg,
-                                           std::vector<std::unique_ptr<const DexFile>>* dex_files) {
-  ScopedTrace trace("Dex file open from Zip " + std::string(location));
-  DCHECK(dex_files != nullptr) << "DexFile::OpenFromZip: out-param is nullptr";
-  ZipOpenErrorCode error_code;
-  std::unique_ptr<const DexFile> dex_file(OpenOneDexFileFromZip(zip_archive,
-                                                                kClassesDex,
-                                                                location,
-                                                                verify,
-                                                                verify_checksum,
-                                                                error_msg,
-                                                                &error_code));
-  if (dex_file.get() == nullptr) {
-    return false;
-  } else {
-    // Had at least classes.dex.
-    dex_files->push_back(std::move(dex_file));
-
-    // Now try some more.
-
-    // We could try to avoid std::string allocations by working on a char array directly. As we
-    // do not expect a lot of iterations, this seems too involved and brittle.
-
-    for (size_t i = 1; ; ++i) {
-      std::string name = GetMultiDexClassesDexName(i);
-      std::string fake_location = GetMultiDexLocation(i, location.c_str());
-      std::unique_ptr<const DexFile> next_dex_file(OpenOneDexFileFromZip(zip_archive,
-                                                                         name.c_str(),
-                                                                         fake_location,
-                                                                         verify,
-                                                                         verify_checksum,
-                                                                         error_msg,
-                                                                         &error_code));
-      if (next_dex_file.get() == nullptr) {
-        if (error_code != ZipOpenErrorCode::kEntryNotFound) {
-          LOG(WARNING) << "Zip open failed: " << *error_msg;
-        }
-        break;
-      } else {
-        dex_files->push_back(std::move(next_dex_file));
-      }
-
-      if (i == kWarnOnManyDexFilesThreshold) {
-        LOG(WARNING) << location << " has in excess of " << kWarnOnManyDexFilesThreshold
-                     << " dex files. Please consider coalescing and shrinking the number to "
-                        " avoid runtime overhead.";
-      }
-
-      if (i == std::numeric_limits<size_t>::max()) {
-        LOG(ERROR) << "Overflow in number of dex files!";
-        break;
-      }
-    }
-
-    return true;
-  }
+bool DexFileLoader::OpenAllDexFilesFromZip(
+    const ZipArchive& zip_archive ATTRIBUTE_UNUSED,
+    const std::string& location ATTRIBUTE_UNUSED,
+    bool verify ATTRIBUTE_UNUSED,
+    bool verify_checksum ATTRIBUTE_UNUSED,
+    std::string* error_msg,
+    std::vector<std::unique_ptr<const DexFile>>* dex_files ATTRIBUTE_UNUSED) const {
+  *error_msg = "UNIMPLEMENTED";
+  return false;
 }
 
 std::unique_ptr<DexFile> DexFileLoader::OpenCommon(const uint8_t* base,
diff --git a/runtime/dex/dex_file_loader.h b/runtime/dex/dex_file_loader.h
index 7db8d8e..6f1afd6 100644
--- a/runtime/dex/dex_file_loader.h
+++ b/runtime/dex/dex_file_loader.h
@@ -46,6 +46,8 @@
   // Return true if the corresponding version and magic is valid.
   static bool IsVersionAndMagicValid(const uint8_t* magic);
 
+  virtual ~DexFileLoader() { }
+
   // Returns the checksums of a file for comparison with GetLocationChecksum().
   // For .dex files, this is the single header checksum.
   // For zip files, this is the zip entry CRC32 checksum for classes.dex and
@@ -55,55 +57,55 @@
   // zip_fd is -1, the method will try to open the `filename` and read the
   // content from it.
   // Return true if the checksums could be found, false otherwise.
-  static bool GetMultiDexChecksums(const char* filename,
-                                   std::vector<uint32_t>* checksums,
-                                   std::string* error_msg,
-                                   int zip_fd = -1);
+  virtual bool GetMultiDexChecksums(const char* filename,
+                                    std::vector<uint32_t>* checksums,
+                                    std::string* error_msg,
+                                    int zip_fd = -1) const;
 
   // Check whether a location denotes a multidex dex file. This is a very simple check: returns
   // whether the string contains the separator character.
   static bool IsMultiDexLocation(const char* location);
 
   // Opens .dex file, backed by existing memory
-  static std::unique_ptr<const DexFile> Open(const uint8_t* base,
-                                             size_t size,
-                                             const std::string& location,
-                                             uint32_t location_checksum,
-                                             const OatDexFile* oat_dex_file,
-                                             bool verify,
-                                             bool verify_checksum,
-                                             std::string* error_msg);
+  virtual std::unique_ptr<const DexFile> Open(const uint8_t* base,
+                                              size_t size,
+                                              const std::string& location,
+                                              uint32_t location_checksum,
+                                              const OatDexFile* oat_dex_file,
+                                              bool verify,
+                                              bool verify_checksum,
+                                              std::string* error_msg) const;
 
   // Opens .dex file that has been memory-mapped by the caller.
-  static std::unique_ptr<const DexFile> Open(const std::string& location,
-                                             uint32_t location_checkum,
-                                             std::unique_ptr<MemMap> mem_map,
-                                             bool verify,
-                                             bool verify_checksum,
-                                             std::string* error_msg);
+  virtual std::unique_ptr<const DexFile> Open(const std::string& location,
+                                              uint32_t location_checkum,
+                                              std::unique_ptr<MemMap> mem_map,
+                                              bool verify,
+                                              bool verify_checksum,
+                                              std::string* error_msg) const;
 
   // Opens all .dex files found in the file, guessing the container format based on file extension.
-  static bool Open(const char* filename,
-                   const std::string& location,
-                   bool verify,
-                   bool verify_checksum,
-                   std::string* error_msg,
-                   std::vector<std::unique_ptr<const DexFile>>* dex_files);
+  virtual bool Open(const char* filename,
+                    const std::string& location,
+                    bool verify,
+                    bool verify_checksum,
+                    std::string* error_msg,
+                    std::vector<std::unique_ptr<const DexFile>>* dex_files) const;
 
   // Open a single dex file from an fd. This function closes the fd.
-  static std::unique_ptr<const DexFile> OpenDex(int fd,
-                                                const std::string& location,
-                                                bool verify,
-                                                bool verify_checksum,
-                                                std::string* error_msg);
+  virtual std::unique_ptr<const DexFile> OpenDex(int fd,
+                                                 const std::string& location,
+                                                 bool verify,
+                                                 bool verify_checksum,
+                                                 std::string* error_msg) const;
 
   // Opens dex files from within a .jar, .zip, or .apk file
-  static bool OpenZip(int fd,
-                      const std::string& location,
-                      bool verify,
-                      bool verify_checksum,
-                      std::string* error_msg,
-                      std::vector<std::unique_ptr<const DexFile>>* dex_files);
+  virtual bool OpenZip(int fd,
+                       const std::string& location,
+                       bool verify,
+                       bool verify_checksum,
+                       std::string* error_msg,
+                       std::vector<std::unique_ptr<const DexFile>>* dex_files) const;
 
   // Return the name of the index-th classes.dex in a multidex zip file. This is classes.dex for
   // index == 0, and classes{index + 1}.dex else.
@@ -148,13 +150,7 @@
     return (pos == std::string::npos) ? std::string() : location.substr(pos);
   }
 
- private:
-  static std::unique_ptr<const DexFile> OpenFile(int fd,
-                                                 const std::string& location,
-                                                 bool verify,
-                                                 bool verify_checksum,
-                                                 std::string* error_msg);
-
+ protected:
   enum class ZipOpenErrorCode {
     kNoError,
     kEntryNotFound,
@@ -164,24 +160,6 @@
     kVerifyError
   };
 
-  // Open all classesXXX.dex files from a zip archive.
-  static bool OpenAllDexFilesFromZip(const ZipArchive& zip_archive,
-                                     const std::string& location,
-                                     bool verify,
-                                     bool verify_checksum,
-                                     std::string* error_msg,
-                                     std::vector<std::unique_ptr<const DexFile>>* dex_files);
-
-  // Opens .dex file from the entry_name in a zip archive. error_code is undefined when non-null
-  // return.
-  static std::unique_ptr<const DexFile> OpenOneDexFileFromZip(const ZipArchive& zip_archive,
-                                                              const char* entry_name,
-                                                              const std::string& location,
-                                                              bool verify,
-                                                              bool verify_checksum,
-                                                              std::string* error_msg,
-                                                              ZipOpenErrorCode* error_code);
-
   enum class VerifyResult {  // private
     kVerifyNotAttempted,
     kVerifySucceeded,
@@ -198,6 +176,31 @@
                                              std::string* error_msg,
                                              DexFileContainer* container,
                                              VerifyResult* verify_result);
+
+ private:
+  virtual std::unique_ptr<const DexFile> OpenFile(int fd,
+                                                  const std::string& location,
+                                                  bool verify,
+                                                  bool verify_checksum,
+                                                  std::string* error_msg) const;
+
+  // Open all classesXXX.dex files from a zip archive.
+  virtual bool OpenAllDexFilesFromZip(const ZipArchive& zip_archive,
+                                      const std::string& location,
+                                      bool verify,
+                                      bool verify_checksum,
+                                      std::string* error_msg,
+                                      std::vector<std::unique_ptr<const DexFile>>* dex_files) const;
+
+  // Opens .dex file from the entry_name in a zip archive. error_code is undefined when non-null
+  // return.
+  virtual std::unique_ptr<const DexFile> OpenOneDexFileFromZip(const ZipArchive& zip_archive,
+                                                               const char* entry_name,
+                                                               const std::string& location,
+                                                               bool verify,
+                                                               bool verify_checksum,
+                                                               std::string* error_msg,
+                                                               ZipOpenErrorCode* error_code) const;
 };
 
 }  // namespace art
diff --git a/runtime/dex/dex_file_test.cc b/runtime/dex/dex_file_test.cc
index 3ee115c..1c8b3e4 100644
--- a/runtime/dex/dex_file_test.cc
+++ b/runtime/dex/dex_file_test.cc
@@ -20,6 +20,7 @@
 
 #include <memory>
 
+#include "art_dex_file_loader.h"
 #include "base/stl_util.h"
 #include "base/unix_file/fd_file.h"
 #include "code_item_accessors-inl.h"
@@ -237,7 +238,8 @@
   ScopedObjectAccess soa(Thread::Current());
   static constexpr bool kVerifyChecksum = true;
   std::vector<std::unique_ptr<const DexFile>> tmp;
-  bool success = DexFileLoader::Open(
+  const ArtDexFileLoader dex_file_loader;
+  bool success = dex_file_loader.Open(
       location, location, /* verify */ true, kVerifyChecksum, error_msg, &tmp);
   if (success) {
     for (std::unique_ptr<const DexFile>& dex_file : tmp) {
@@ -277,12 +279,13 @@
                                                       /* reuse */ false,
                                                       &error_message));
   memcpy(region->Begin(), dex_bytes.data(), dex_bytes.size());
-  std::unique_ptr<const DexFile> dex_file(DexFileLoader::Open(location,
-                                                              location_checksum,
-                                                              std::move(region),
-                                                              /* verify */ true,
-                                                              /* verify_checksum */ true,
-                                                              &error_message));
+  const ArtDexFileLoader dex_file_loader;
+  std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(location,
+                                                               location_checksum,
+                                                               std::move(region),
+                                                               /* verify */ true,
+                                                               /* verify_checksum */ true,
+                                                               &error_message));
   if (expect_success) {
     CHECK(dex_file != nullptr) << error_message;
   } else {
@@ -368,7 +371,8 @@
   static constexpr bool kVerifyChecksum = true;
   std::string error_msg;
   std::vector<std::unique_ptr<const DexFile>> dex_files;
-  ASSERT_FALSE(DexFileLoader::Open(
+  const ArtDexFileLoader dex_file_loader;
+  ASSERT_FALSE(dex_file_loader.Open(
       location, location, /* verify */ true, kVerifyChecksum, &error_msg, &dex_files));
 }
 
@@ -381,7 +385,8 @@
   static constexpr bool kVerifyChecksum = true;
   std::string error_msg;
   std::vector<std::unique_ptr<const DexFile>> dex_files;
-  ASSERT_FALSE(DexFileLoader::Open(
+  const ArtDexFileLoader dex_file_loader;
+  ASSERT_FALSE(dex_file_loader.Open(
       location, location, /* verify */ true, kVerifyChecksum, &error_msg, &dex_files));
 }
 
@@ -394,7 +399,8 @@
   static constexpr bool kVerifyChecksum = true;
   std::string error_msg;
   std::vector<std::unique_ptr<const DexFile>> dex_files;
-  ASSERT_FALSE(DexFileLoader::Open(
+  const ArtDexFileLoader dex_file_loader;
+  ASSERT_FALSE(dex_file_loader.Open(
       location, location, /* verify */ true, kVerifyChecksum, &error_msg, &dex_files));
 }
 
@@ -408,9 +414,10 @@
   std::vector<uint32_t> checksums;
   ScopedObjectAccess soa(Thread::Current());
   std::string error_msg;
-  EXPECT_TRUE(DexFileLoader::GetMultiDexChecksums(GetLibCoreDexFileNames()[0].c_str(),
-                                                  &checksums,
-                                                  &error_msg))
+  const ArtDexFileLoader dex_file_loader;
+  EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(GetLibCoreDexFileNames()[0].c_str(),
+                                                    &checksums,
+                                                    &error_msg))
       << error_msg;
   ASSERT_EQ(1U, checksums.size());
   EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksums[0]);
@@ -420,9 +427,10 @@
   std::string error_msg;
   std::vector<uint32_t> checksums;
   std::string multidex_file = GetTestDexFileName("MultiDex");
-  EXPECT_TRUE(DexFileLoader::GetMultiDexChecksums(multidex_file.c_str(),
-                                                  &checksums,
-                                                  &error_msg)) << error_msg;
+  const ArtDexFileLoader dex_file_loader;
+  EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(multidex_file.c_str(),
+                                                    &checksums,
+                                                    &error_msg)) << error_msg;
 
   std::vector<std::unique_ptr<const DexFile>> dexes = OpenTestDexFiles("MultiDex");
   ASSERT_EQ(2U, dexes.size());
diff --git a/runtime/dex/dex_file_verifier_test.cc b/runtime/dex/dex_file_verifier_test.cc
index d4d912c..9759685 100644
--- a/runtime/dex/dex_file_verifier_test.cc
+++ b/runtime/dex/dex_file_verifier_test.cc
@@ -22,6 +22,7 @@
 #include <functional>
 #include <memory>
 
+#include "art_dex_file_loader.h"
 #include "base/bit_utils.h"
 #include "base/macros.h"
 #include "base/unix_file/fd_file.h"
@@ -114,7 +115,8 @@
   // read dex file
   ScopedObjectAccess soa(Thread::Current());
   std::vector<std::unique_ptr<const DexFile>> tmp;
-  bool success = DexFileLoader::Open(
+  const ArtDexFileLoader dex_file_loader;
+  bool success = dex_file_loader.Open(
       location, location, /* verify */ true, /* verify_checksum */ true, error_msg, &tmp);
   CHECK(success) << *error_msg;
   EXPECT_EQ(1U, tmp.size());
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
index e459f09..20cde53 100644
--- a/runtime/dex2oat_environment_test.h
+++ b/runtime/dex2oat_environment_test.h
@@ -27,6 +27,7 @@
 #include "base/stl_util.h"
 #include "common_runtime_test.h"
 #include "compiler_callbacks.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file_loader.h"
 #include "exec_utils.h"
 #include "gc/heap.h"
@@ -43,6 +44,7 @@
  public:
   virtual void SetUp() OVERRIDE {
     CommonRuntimeTest::SetUp();
+    const ArtDexFileLoader dex_file_loader;
 
     // Create a scratch directory to work from.
 
@@ -74,7 +76,7 @@
     ASSERT_TRUE(OS::FileExists(GetStrippedDexSrc1().c_str()))
       << "Expected stripped dex file to be at: " << GetStrippedDexSrc1();
     ASSERT_FALSE(
-        DexFileLoader::GetMultiDexChecksums(GetStrippedDexSrc1().c_str(), &checksums, &error_msg))
+        dex_file_loader.GetMultiDexChecksums(GetStrippedDexSrc1().c_str(), &checksums, &error_msg))
       << "Expected stripped dex file to be stripped: " << GetStrippedDexSrc1();
     ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str()))
       << "Expected dex file to be at: " << GetDexSrc2();
@@ -83,21 +85,21 @@
     // GetMultiDexSrc1, but a different secondary dex checksum.
     static constexpr bool kVerifyChecksum = true;
     std::vector<std::unique_ptr<const DexFile>> multi1;
-    ASSERT_TRUE(DexFileLoader::Open(GetMultiDexSrc1().c_str(),
-                                    GetMultiDexSrc1().c_str(),
-                                    /* verify */ true,
-                                    kVerifyChecksum,
-                                    &error_msg,
-                                    &multi1)) << error_msg;
+    ASSERT_TRUE(dex_file_loader.Open(GetMultiDexSrc1().c_str(),
+                                     GetMultiDexSrc1().c_str(),
+                                     /* verify */ true,
+                                     kVerifyChecksum,
+                                     &error_msg,
+                                     &multi1)) << error_msg;
     ASSERT_GT(multi1.size(), 1u);
 
     std::vector<std::unique_ptr<const DexFile>> multi2;
-    ASSERT_TRUE(DexFileLoader::Open(GetMultiDexSrc2().c_str(),
-                                    GetMultiDexSrc2().c_str(),
-                                    /* verify */ true,
-                                    kVerifyChecksum,
-                                    &error_msg,
-                                    &multi2)) << error_msg;
+    ASSERT_TRUE(dex_file_loader.Open(GetMultiDexSrc2().c_str(),
+                                     GetMultiDexSrc2().c_str(),
+                                     /* verify */ true,
+                                     kVerifyChecksum,
+                                     &error_msg,
+                                     &multi2)) << error_msg;
     ASSERT_GT(multi2.size(), 1u);
 
     ASSERT_EQ(multi1[0]->GetLocationChecksum(), multi2[0]->GetLocationChecksum());
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 251d94c..ca5a3ee 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -36,6 +36,7 @@
 #include "base/stl_util.h"
 #include "base/systrace.h"
 #include "base/time_utils.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file_loader.h"
 #include "exec_utils.h"
 #include "gc/accounting/space_bitmap-inl.h"
@@ -1828,6 +1829,7 @@
 }
 
 bool ImageSpace::ValidateOatFile(const OatFile& oat_file, std::string* error_msg) {
+  const ArtDexFileLoader dex_file_loader;
   for (const OatFile::OatDexFile* oat_dex_file : oat_file.GetOatDexFiles()) {
     const std::string& dex_file_location = oat_dex_file->GetDexFileLocation();
 
@@ -1838,7 +1840,7 @@
     }
 
     std::vector<uint32_t> checksums;
-    if (!DexFileLoader::GetMultiDexChecksums(dex_file_location.c_str(), &checksums, error_msg)) {
+    if (!dex_file_loader.GetMultiDexChecksums(dex_file_location.c_str(), &checksums, error_msg)) {
       *error_msg = StringPrintf("ValidateOatFile failed to get checksums of dex file '%s' "
                                 "referenced by oat file %s: %s",
                                 dex_file_location.c_str(),
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index a992b5c..0f43087 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -27,6 +27,7 @@
 #include <class_loader_context.h>
 #include "common_throws.h"
 #include "compiler_filter.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
 #include "jni_internal.h"
@@ -188,12 +189,13 @@
                                       dex_mem_map->Begin(),
                                       dex_mem_map->End());
   std::string error_message;
-  std::unique_ptr<const DexFile> dex_file(DexFileLoader::Open(location,
-                                                              0,
-                                                              std::move(dex_mem_map),
-                                                              /* verify */ true,
-                                                              /* verify_location */ true,
-                                                              &error_message));
+  const ArtDexFileLoader dex_file_loader;
+  std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(location,
+                                                               0,
+                                                               std::move(dex_mem_map),
+                                                               /* verify */ true,
+                                                               /* verify_location */ true,
+                                                               &error_message));
   if (dex_file == nullptr) {
     ScopedObjectAccess soa(env);
     ThrowWrappedIOException("%s", error_message.c_str());
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index c666441..446a004 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -43,6 +43,7 @@
 #include "base/stl_util.h"
 #include "base/systrace.h"
 #include "base/unix_file/fd_file.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file_loader.h"
 #include "dex/dex_file_types.h"
 #include "dex/standard_dex_file.h"
@@ -1666,14 +1667,15 @@
   ScopedTrace trace(__PRETTY_FUNCTION__);
   static constexpr bool kVerify = false;
   static constexpr bool kVerifyChecksum = false;
-  return DexFileLoader::Open(dex_file_pointer_,
-                             FileSize(),
-                             dex_file_location_,
-                             dex_file_location_checksum_,
-                             this,
-                             kVerify,
-                             kVerifyChecksum,
-                             error_msg);
+  const ArtDexFileLoader dex_file_loader;
+  return dex_file_loader.Open(dex_file_pointer_,
+                              FileSize(),
+                              dex_file_location_,
+                              dex_file_location_checksum_,
+                              this,
+                              kVerify,
+                              kVerifyChecksum,
+                              error_msg);
 }
 
 uint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 240030c..73ca19a 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -28,6 +28,7 @@
 #include "base/stl_util.h"
 #include "class_linker.h"
 #include "compiler_filter.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file_loader.h"
 #include "exec_utils.h"
 #include "gc/heap.h"
@@ -869,10 +870,11 @@
     required_dex_checksums_found_ = false;
     cached_required_dex_checksums_.clear();
     std::string error_msg;
-    if (DexFileLoader::GetMultiDexChecksums(dex_location_.c_str(),
-                                            &cached_required_dex_checksums_,
-                                            &error_msg,
-                                            zip_fd_)) {
+    const ArtDexFileLoader dex_file_loader;
+    if (dex_file_loader.GetMultiDexChecksums(dex_location_.c_str(),
+                                             &cached_required_dex_checksums_,
+                                             &error_msg,
+                                             zip_fd_)) {
       required_dex_checksums_found_ = true;
       has_original_dex_files_ = true;
     } else {
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 29b9bfc..e126c16 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -31,6 +31,7 @@
 #include "base/systrace.h"
 #include "class_linker.h"
 #include "class_loader_context.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
 #include "dex/dex_file_tracking_registrar.h"
@@ -606,12 +607,13 @@
     if (oat_file_assistant.HasOriginalDexFiles()) {
       if (Runtime::Current()->IsDexFileFallbackEnabled()) {
         static constexpr bool kVerifyChecksum = true;
-        if (!DexFileLoader::Open(dex_location,
-                                 dex_location,
-                                 Runtime::Current()->IsVerificationEnabled(),
-                                 kVerifyChecksum,
-                                 /*out*/ &error_msg,
-                                 &dex_files)) {
+        const ArtDexFileLoader dex_file_loader;
+        if (!dex_file_loader.Open(dex_location,
+                                  dex_location,
+                                  Runtime::Current()->IsVerificationEnabled(),
+                                  kVerifyChecksum,
+                                  /*out*/ &error_msg,
+                                  &dex_files)) {
           LOG(WARNING) << error_msg;
           error_msgs->push_back("Failed to open dex files from " + std::string(dex_location)
                                 + " because: " + error_msg);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 38c2bfd..b4284bb 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -69,6 +69,7 @@
 #include "class_linker-inl.h"
 #include "compiler_callbacks.h"
 #include "debugger.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file_loader.h"
 #include "elf_file.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
@@ -1041,6 +1042,7 @@
   if (!image_location.empty() && OpenDexFilesFromImage(image_location, dex_files, &failure_count)) {
     return failure_count;
   }
+  const ArtDexFileLoader dex_file_loader;
   failure_count = 0;
   for (size_t i = 0; i < dex_filenames.size(); i++) {
     const char* dex_filename = dex_filenames[i].c_str();
@@ -1051,12 +1053,12 @@
       LOG(WARNING) << "Skipping non-existent dex file '" << dex_filename << "'";
       continue;
     }
-    if (!DexFileLoader::Open(dex_filename,
-                             dex_location,
-                             Runtime::Current()->IsVerificationEnabled(),
-                             kVerifyChecksum,
-                             &error_msg,
-                             dex_files)) {
+    if (!dex_file_loader.Open(dex_filename,
+                              dex_location,
+                              Runtime::Current()->IsVerificationEnabled(),
+                              kVerifyChecksum,
+                              &error_msg,
+                              dex_files)) {
       LOG(WARNING) << "Failed to open .dex from file '" << dex_filename << "': " << error_msg;
       ++failure_count;
     }
diff --git a/runtime/utils.cc b/runtime/utils.cc
index bd4175f..79ddcb9 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -26,10 +26,10 @@
 
 #include <memory>
 
+#include "android-base/file.h"
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
 
-#include "base/file_utils.h"
 #include "dex/dex_file-inl.h"
 #include "os.h"
 #include "utf-inl.h"
@@ -46,6 +46,7 @@
 
 namespace art {
 
+using android::base::ReadFileToString;
 using android::base::StringAppendF;
 using android::base::StringPrintf;
 
@@ -63,6 +64,7 @@
 
 std::string GetThreadName(pid_t tid) {
   std::string result;
+  // TODO: make this less Linux-specific.
   if (ReadFileToString(StringPrintf("/proc/self/task/%d/comm", tid), &result)) {
     result.resize(result.size() - 1);  // Lose the trailing '\n'.
   } else {
@@ -611,6 +613,7 @@
 void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) {
   *utime = *stime = *task_cpu = 0;
   std::string stats;
+  // TODO: make this less Linux-specific.
   if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
     return;
   }
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index c536054..c16cfb6 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -25,6 +25,7 @@
 #include "base/bit_utils.h"
 #include "base/stl_util.h"
 #include "base/unix_file/fd_file.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file.h"
 #include "dex/dex_file_loader.h"
 #include "dex_to_dex_decompiler.h"
@@ -171,6 +172,7 @@
 
 bool VdexFile::OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
                                std::string* error_msg) {
+  const ArtDexFileLoader dex_file_loader;
   size_t i = 0;
   for (const uint8_t* dex_file_start = GetNextDexFileData(nullptr);
        dex_file_start != nullptr;
@@ -179,14 +181,14 @@
     // TODO: Supply the location information for a vdex file.
     static constexpr char kVdexLocation[] = "";
     std::string location = DexFileLoader::GetMultiDexLocation(i, kVdexLocation);
-    std::unique_ptr<const DexFile> dex(DexFileLoader::Open(dex_file_start,
-                                                           size,
-                                                           location,
-                                                           GetLocationChecksum(i),
-                                                           nullptr /*oat_dex_file*/,
-                                                           false /*verify*/,
-                                                           false /*verify_checksum*/,
-                                                           error_msg));
+    std::unique_ptr<const DexFile> dex(dex_file_loader.Open(dex_file_start,
+                                                            size,
+                                                            location,
+                                                            GetLocationChecksum(i),
+                                                            nullptr /*oat_dex_file*/,
+                                                            false /*verify*/,
+                                                            false /*verify_checksum*/,
+                                                            error_msg));
     if (dex == nullptr) {
       return false;
     }
diff --git a/test/983-source-transform-verify/source_transform.cc b/test/983-source-transform-verify/source_transform.cc
index e9cb35e..c076d15 100644
--- a/test/983-source-transform-verify/source_transform.cc
+++ b/test/983-source-transform-verify/source_transform.cc
@@ -28,6 +28,7 @@
 #include "base/macros.h"
 #include "bytecode_utils.h"
 #include "dex/code_item_accessors-inl.h"
+#include "dex/art_dex_file_loader.h"
 #include "dex/dex_file.h"
 #include "dex/dex_file_loader.h"
 #include "dex/dex_instruction.h"
@@ -66,15 +67,16 @@
   if (IsJVM()) {
     return;
   }
+  const ArtDexFileLoader dex_file_loader;
   std::string error;
-  std::unique_ptr<const DexFile> dex(DexFileLoader::Open(class_data,
-                                                         class_data_len,
-                                                         "fake_location.dex",
-                                                         /*location_checksum*/ 0,
-                                                         /*oat_dex_file*/ nullptr,
-                                                         /*verify*/ true,
-                                                         /*verify_checksum*/ true,
-                                                         &error));
+  std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data,
+                                                          class_data_len,
+                                                          "fake_location.dex",
+                                                          /*location_checksum*/ 0,
+                                                          /*oat_dex_file*/ nullptr,
+                                                          /*verify*/ true,
+                                                          /*verify_checksum*/ true,
+                                                          &error));
   if (dex.get() == nullptr) {
     std::cout << "Failed to verify dex file for " << name << " because " << error << std::endl;
     return;