user build support for art (2 of 3)

Change-Id: I4696fee58e43db48540e2442c4235fc4bb02d9e3
diff --git a/Android.mk b/Android.mk
index 9f425c8..b648d54 100644
--- a/Android.mk
+++ b/Android.mk
@@ -129,7 +129,7 @@
 ART_CACHE_OATS :=
 # $(1): name
 define build-art-cache-oat
-  $(call build-art-oat,$(PRODUCT_OUT)/$(1),$(call art-cache-oat,$(1)),$(TARGET_BOOT_IMG))
+  $(call build-art-oat,$(PRODUCT_OUT)/$(1),/$(1),$(call art-cache-oat,$(1)),$(TARGET_BOOT_IMG))
   ART_CACHE_OATS += $(call art-cache-oat,$(1))
 endef
 
@@ -144,7 +144,7 @@
   $(eval $(call build-art-cache-oat,$(subst $(PRODUCT_OUT)/,,$(file)))))
 
 .PHONY: oat-target-sync
-oat-target-sync: $(ART_TARGET_DEPENDENCIES) $(TARGET_BOOT_OAT) $(ART_CACHE_OATS)
+oat-target-sync: $(ART_TARGET_DEPENDENCIES) $(TARGET_BOOT_OAT_OUT) $(ART_CACHE_OATS)
 	adb remount
 	adb sync
 
@@ -155,17 +155,17 @@
 dump-oat: dump-oat-core dump-oat-boot dump-oat-Calculator
 
 .PHONY: dump-oat-core
-dump-oat-core: $(TARGET_CORE_OAT) $(OATDUMP)
-	$(OATDUMP) --image=$(TARGET_CORE_IMG) --host-prefix=$(PRODUCT_OUT) --output=/tmp/core.oatdump.txt
+dump-oat-core: $(TARGET_CORE_OAT_OUT) $(OATDUMP)
+	$(OATDUMP) --image=$(TARGET_CORE_IMG_OUT) --host-prefix=$(PRODUCT_OUT) --output=/tmp/core.oatdump.txt
 	@echo Output in /tmp/core.oatdump.txt
 
 .PHONY: dump-oat-boot
-dump-oat-boot: $(TARGET_BOOT_OAT) $(OATDUMP)
-	$(OATDUMP) --image=$(TARGET_BOOT_IMG) --host-prefix=$(PRODUCT_OUT) --output=/tmp/boot.oatdump.txt
+dump-oat-boot: $(TARGET_BOOT_OAT_OUT) $(OATDUMP)
+	$(OATDUMP) --image=$(TARGET_BOOT_IMG_OUT) --host-prefix=$(PRODUCT_OUT) --output=/tmp/boot.oatdump.txt
 	@echo Output in /tmp/boot.oatdump.txt
 
 .PHONY: dump-oat-Calculator
-dump-oat-Calculator: $(call art-cache-oat,system/app/Calculator.apk) $(TARGET_BOOT_OAT) $(OATDUMP)
+dump-oat-Calculator: $(call art-cache-oat,system/app/Calculator.apk) $(TARGET_BOOT_OAT_OUT) $(OATDUMP)
 	$(OATDUMP) --oat-file=$< --boot-image=$(TARGET_BOOT_IMG) --host-prefix=$(PRODUCT_OUT) --output=/tmp/Calculator.oatdump.txt
 	@echo Output in /tmp/Calculator.oatdump.txt
 
@@ -176,14 +176,26 @@
 
 .PHONY: clean-oat
 clean-oat:
+	rm -f $(ART_NATIVETEST_OUT)/*.oat
+	rm -f $(ART_NATIVETEST_OUT)/*.art
 	rm -f $(ART_TEST_OUT)/*.oat
 	rm -f $(ART_TEST_OUT)/*.art
 	rm -f $(ART_CACHE_OUT)/*.oat
 	rm -f $(ART_CACHE_OUT)/*.art
+	rm -f $(HOST_OUT_JAVA_LIBRARIES)/*.oat
+	rm -f $(HOST_OUT_JAVA_LIBRARIES)/*.art
+	rm -f $(TARGET_OUT_JAVA_LIBRARIES)/*.oat
+	rm -f $(TARGET_OUT_JAVA_LIBRARIES)/*.art
+	rm -f $(TARGET_OUT_APPS)/*.oat
+	adb shell rm $(ART_NATIVETEST_DIR)/*.oat
+	adb shell rm $(ART_NATIVETEST_DIR)/*.art
 	adb shell rm $(ART_TEST_DIR)/*.oat
 	adb shell rm $(ART_TEST_DIR)/*.art
 	adb shell rm $(ART_CACHE_DIR)/*.oat
 	adb shell rm $(ART_CACHE_DIR)/*.art
+	adb shell rm $(DEXPREOPT_BOOT_JAR_DIR)/*.oat
+	adb shell rm $(DEXPREOPT_BOOT_JAR_DIR)/*.art
+	adb shell rm system/app/*.oat
 
 ########################################################################
 # cpplint target
diff --git a/build/Android.common.mk b/build/Android.common.mk
index c7bfbe5..853c4d2 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -31,6 +31,11 @@
 ART_CACHE_OUT := $(TARGET_OUT_DATA)/art-cache
 
 # $(1): pathname
+define art-cache-dir
+$(ART_CACHE_DIR)/$(subst /,@,$(1))
+endef
+
+# $(1): pathname
 define art-cache-out
 $(ART_CACHE_OUT)/$(subst /,@,$(1))
 endef
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index 4f1bb2d..4f8ff2b 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -39,50 +39,59 @@
 HOST_CORE_JARS := core-hostdex
 TARGET_CORE_JARS := core
 
-HOST_CORE_DEX   := $(foreach jar,$(HOST_CORE_JARS),  $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
-TARGET_CORE_DEX := $(foreach jar,$(TARGET_CORE_JARS),$(TARGET_OUT_JAVA_LIBRARIES)/$(jar).jar)
+HOST_CORE_DEX_LOCATIONS   := $(foreach jar,$(HOST_CORE_JARS),  $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
+TARGET_CORE_DEX_LOCATIONS := $(foreach jar,$(TARGET_CORE_JARS),/$(DEXPREOPT_BOOT_JAR_DIR)/$(jar).jar)
+
+HOST_CORE_DEX_FILES   := $(foreach jar,$(HOST_CORE_JARS),  $(call intermediates-dir-for,JAVA_LIBRARIES,$(jar),t,COMMON)/javalib.jar)
+TARGET_CORE_DEX_FILES := $(foreach jar,$(TARGET_CORE_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar), ,COMMON)/javalib.jar)
 
 HOST_CORE_OAT := $(HOST_OUT_JAVA_LIBRARIES)/core.oat
-TARGET_CORE_OAT := $(ART_TEST_OUT)/core.oat
+TARGET_CORE_OAT := $(ART_TEST_DIR)/core.oat
 
-HOST_CORE_IMG := $(HOST_OUT_JAVA_LIBRARIES)/core.art
-TARGET_CORE_IMG := $(ART_TEST_OUT)/core.art
+HOST_CORE_OAT_OUT := $(HOST_OUT_JAVA_LIBRARIES)/core.oat
+TARGET_CORE_OAT_OUT := $(ART_TEST_OUT)/core.oat
 
-$(HOST_CORE_OAT): $(HOST_CORE_DEX) $(DEX2OAT_DEPENDENCY)
+HOST_CORE_IMG_OUT := $(HOST_OUT_JAVA_LIBRARIES)/core.art
+TARGET_CORE_IMG_OUT := $(ART_TEST_OUT)/core.art
+
+$(HOST_CORE_OAT_OUT): $(HOST_CORE_DEX_FILES) $(DEX2OAT_DEPENDENCY)
 	@echo "host dex2oat: $@ ($?)"
 	@mkdir -p $(dir $@)
-	$(hide) $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat-file=$@ --image=$(HOST_CORE_IMG) --base=$(IMG_HOST_BASE_ADDRESS)
+	$(hide) $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(HOST_CORE_DEX_FILES)) $(addprefix --dex-location=,$(HOST_CORE_DEX_LOCATIONS)) --oat-file=$@ --oat-location=$(HOST_CORE_OAT) --image=$(HOST_CORE_IMG_OUT) --base=$(IMG_HOST_BASE_ADDRESS)
 
-$(TARGET_CORE_OAT): $(TARGET_CORE_DEX) $(DEX2OAT_DEPENDENCY)
+$(TARGET_CORE_OAT_OUT): $(TARGET_CORE_DEX) $(DEX2OAT_DEPENDENCY)
 	@echo "target dex2oat: $@ ($?)"
 	@mkdir -p $(dir $@)
-	$(hide) $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat-file=$@ --image=$(TARGET_CORE_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
+	$(hide) $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(TARGET_CORE_DEX_FILES)) $(addprefix --dex-location=,$(TARGET_CORE_DEX_LOCATIONS)) --oat-file=$@ --oat-location=$(TARGET_CORE_OAT) --image=$(TARGET_CORE_IMG_OUT) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
 
-$(HOST_CORE_IMG): $(HOST_CORE_OAT)
+$(HOST_CORE_IMG_OUT): $(HOST_CORE_OAT_OUT)
 
-$(TARGET_CORE_IMG): $(TARGET_CORE_OAT)
+$(TARGET_CORE_IMG_OUT): $(TARGET_CORE_OAT_OUT)
 
 ########################################################################
 # The full system boot classpath
 TARGET_BOOT_JARS := $(subst :, ,$(DEXPREOPT_BOOT_JARS))
-TARGET_BOOT_DEX := $(foreach jar,$(TARGET_BOOT_JARS),$(TARGET_OUT_JAVA_LIBRARIES)/$(jar).jar)
+TARGET_BOOT_DEX_LOCATIONS := $(foreach jar,$(TARGET_BOOT_JARS),/$(DEXPREOPT_BOOT_JAR_DIR)/$(jar).jar)
+TARGET_BOOT_DEX_FILES := $(foreach jar,$(TARGET_BOOT_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar),,COMMON)/javalib.jar)
 ifeq ($(TARGET_PRODUCT),$(filter $(TARGET_PRODUCT),trygon))
-  TARGET_BOOT_OAT := $(call art-cache-out,$(DEXPREOPT_BOOT_JAR_DIR)/boot.oat)
-  TARGET_BOOT_IMG := $(call art-cache-out,$(DEXPREOPT_BOOT_JAR_DIR)/boot.art)
+  TARGET_BOOT_OAT := $(call art-cache-dir,$(DEXPREOPT_BOOT_JAR_DIR)/boot.oat)
+  TARGET_BOOT_OAT_OUT := $(call art-cache-out,$(DEXPREOPT_BOOT_JAR_DIR)/boot.oat)
+  TARGET_BOOT_IMG_OUT := $(call art-cache-out,$(DEXPREOPT_BOOT_JAR_DIR)/boot.art)
 else
-  TARGET_BOOT_OAT := $(TARGET_OUT_JAVA_LIBRARIES)/boot.oat
-  TARGET_BOOT_IMG := $(TARGET_OUT_JAVA_LIBRARIES)/boot.art
+  TARGET_BOOT_OAT := /$(DEXPREOPT_BOOT_JAR_DIR)/boot.oat
+  TARGET_BOOT_OAT_OUT := $(TARGET_OUT_JAVA_LIBRARIES)/boot.oat
+  TARGET_BOOT_IMG_OUT := $(TARGET_OUT_JAVA_LIBRARIES)/boot.art
 endif
 
-$(TARGET_BOOT_OAT): $(TARGET_BOOT_DEX) $(DEX2OAT_DEPENDENCY)
+$(TARGET_BOOT_OAT_OUT): $(TARGET_BOOT_DEX_FILES) $(DEX2OAT_DEPENDENCY)
 	@echo "target dex2oat: $@ ($?)"
 	@mkdir -p $(dir $@)
-	$(hide) $(DEX2OAT) --runtime-arg -Xms256m --runtime-arg -Xmx256m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat-file=$@ --image=$(TARGET_BOOT_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
+	$(hide) $(DEX2OAT) --runtime-arg -Xms256m --runtime-arg -Xmx256m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(TARGET_BOOT_DEX_FILES)) $(addprefix --dex-location=,$(TARGET_BOOT_DEX_LOCATIONS)) --oat-file=$@ --oat-location=$(TARGET_BOOT_OAT) --image=$(TARGET_BOOT_IMG_OUT) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
 
-$(TARGET_BOOT_IMG): $(TARGET_BOOT_OAT)
+$(TARGET_BOOT_IMG_OUT): $(TARGET_BOOT_OAT_OUT)
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := boot.art
 LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_BOOT_IMG)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_BOOT_IMG_OUT)
 include $(BUILD_PHONY_PACKAGE)
diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk
index 49700f2..7e630c7 100644
--- a/build/Android.oattest.mk
+++ b/build/Android.oattest.mk
@@ -38,13 +38,14 @@
 ########################################################################
 
 # $(1): input jar or apk filename
-# $(2): output oat filename
-# $(3): boot image
+# $(2): input jar or apk target location
+# $(3): output oat filename
+# $(4): boot image
 define build-art-oat
-$(2): $(1) $(3) $(DEX2OAT_DEPENDENCY)
+$(3): $(1) $(4) $(DEX2OAT_DEPENDENCY)
 	@echo "target dex2oat: $$@ ($$?)"
 	@mkdir -p $$(dir $$@)
-	$(hide) $(DEX2OAT) --runtime-arg -Xms64m --runtime-arg -Xmx64m --boot-image=$(3) $(addprefix --dex-file=,$$<) --oat-file=$$@ --host-prefix=$(PRODUCT_OUT)
+	$(hide) $(DEX2OAT) --runtime-arg -Xms64m --runtime-arg -Xmx64m --boot-image=$(4) --dex-file=$(1) --dex-location=$(2) --oat-file=$$@ --host-prefix=$(PRODUCT_OUT)
 endef
 
 ########################################################################
@@ -52,10 +53,12 @@
 
 # $(1): directory
 define build-art-test-oat
-  $(call build-art-oat,$(ART_TEST_OUT)/oat-test-dex-$(1).jar,$(ART_TEST_OUT)/oat-test-dex-$(1).jar.oat,$(TARGET_CORE_IMG))
+  $(call build-art-oat,$(call intermediates-dir-for,JAVA_LIBRARIES,oat-test-dex-$(dir),,COMMON)/javalib.jar,$(ART_TEST_DIR)/oat-test-dex-$(1).jar,$(ART_TEST_OUT)/oat-test-dex-$(1).jar.oat,$(TARGET_CORE_IMG_OUT))
   ART_TEST_OAT_FILES += $(ART_TEST_OUT)/oat-test-dex-$(1).jar.oat
 endef
-$(foreach dir,$(TEST_OAT_DIRECTORIES), $(eval $(call build-art-test-oat,$(dir))))
+ifneq (user,$(TARGET_BUILD_VARIANT))
+  $(foreach dir,$(TEST_OAT_DIRECTORIES), $(eval $(call build-art-test-oat,$(dir))))
+endif
 
 ########################################################################
 
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 952bacf..d8bf664 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -209,14 +209,15 @@
   "[Ljava/lang/StackTraceElement;",
 };
 
-ClassLinker* ClassLinker::Create(const std::string& boot_class_path, InternTable* intern_table) {
+ClassLinker* ClassLinker::CreateFromCompiler(const std::vector<const DexFile*>& boot_class_path,
+                                             InternTable* intern_table) {
   CHECK_NE(boot_class_path.size(), 0U);
   UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
-  class_linker->Init(boot_class_path);
+  class_linker->InitFromCompiler(boot_class_path);
   return class_linker.release();
 }
 
-ClassLinker* ClassLinker::Create(InternTable* intern_table) {
+ClassLinker* ClassLinker::CreateFromImage(InternTable* intern_table) {
   UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
   class_linker->InitFromImage();
   return class_linker.release();
@@ -232,22 +233,9 @@
   CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax));
 }
 
-void CreateClassPath(const std::string& class_path,
-                     std::vector<const DexFile*>& class_path_vector) {
-  std::vector<std::string> parsed;
-  Split(class_path, ':', parsed);
-  for (size_t i = 0; i < parsed.size(); ++i) {
-    const DexFile* dex_file = DexFile::Open(parsed[i], Runtime::Current()->GetHostPrefix());
-    if (dex_file == NULL) {
-      LOG(WARNING) << "Failed to open dex file " << parsed[i];
-    } else {
-      class_path_vector.push_back(dex_file);
-    }
-  }
-}
-
-void ClassLinker::Init(const std::string& boot_class_path) {
-  VLOG(startup) << "ClassLinker::InitFrom entering boot_class_path=" << boot_class_path;
+void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class_path) {
+  VLOG(startup) << "ClassLinker::Init";
+  CHECK(Runtime::Current()->IsCompiler());
 
   CHECK(!init_done_);
 
@@ -321,11 +309,9 @@
 
   // setup boot_class_path_ and register class_path now that we can
   // use AllocObjectArray to create DexCache instances
-  std::vector<const DexFile*> boot_class_path_vector;
-  CreateClassPath(boot_class_path, boot_class_path_vector);
-  CHECK_NE(0U, boot_class_path_vector.size());
-  for (size_t i = 0; i != boot_class_path_vector.size(); ++i) {
-    const DexFile* dex_file = boot_class_path_vector[i];
+  CHECK_NE(0U, boot_class_path.size());
+  for (size_t i = 0; i != boot_class_path.size(); ++i) {
+    const DexFile* dex_file = boot_class_path[i];
     CHECK(dex_file != NULL);
     AppendToBootClassPath(*dex_file);
   }
@@ -481,7 +467,7 @@
 
   FinishInit();
 
-  VLOG(startup) << "ClassLinker::InitFrom exiting";
+  VLOG(startup) << "ClassLinker::InitFromCompiler exiting";
 }
 
 void ClassLinker::FinishInit() {
@@ -575,7 +561,7 @@
 #endif
   const char* dex2oat = dex2oat_string.c_str();
 
-  const char* class_path = Runtime::Current()->GetClassPath().c_str();
+  const char* class_path = Runtime::Current()->GetClassPathString().c_str();
 
   std::string boot_image_option_string("--boot-image=");
   boot_image_option_string += Heap::GetSpaces()[0]->AsImageSpace()->GetImageFilename();
@@ -589,9 +575,9 @@
   StringAppendF(&oat_fd_option_string, "%d", oat_fd);
   const char* oat_fd_option = oat_fd_option_string.c_str();
 
-  std::string oat_name_option_string("--oat-name=");
-  oat_name_option_string += oat_cache_filename;
-  const char* oat_name_option = oat_name_option_string.c_str();
+  std::string oat_location_option_string("--oat-location=");
+  oat_location_option_string += oat_cache_filename;
+  const char* oat_location_option = oat_location_option_string.c_str();
 
   // fork and exec dex2oat
   pid_t pid = fork();
@@ -609,7 +595,7 @@
                        << " " << boot_image_option
                        << " " << dex_file_option
                        << " " << oat_fd_option
-                       << " " << oat_name_option;
+                       << " " << oat_location_option;
 
     execl(dex2oat, dex2oat,
           "--runtime-arg", "-Xms64m",
@@ -619,7 +605,7 @@
           boot_image_option,
           dex_file_option,
           oat_fd_option,
-          oat_name_option,
+          oat_location_option,
           NULL);
 
     PLOG(FATAL) << "execl(" << dex2oat << ") failed";
@@ -660,7 +646,7 @@
   std::string oat_filename;
   oat_filename += runtime->GetHostPrefix();
   oat_filename += oat_location->ToModifiedUtf8();
-  OatFile* oat_file = OatFile::Open(oat_filename, "", image_header.GetOatBegin());
+  OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, image_header.GetOatBegin());
   VLOG(startup) << "ClassLinker::OpenOat entering oat_filename=" << oat_filename;
   if (oat_file == NULL) {
     LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image.";
@@ -680,18 +666,15 @@
 }
 
 const OatFile* ClassLinker::FindOpenedOatFileForDexFile(const DexFile& dex_file) {
-  return FindOpenedOatFileFromDexLocation(dex_file.GetLocation(),
-                                          dex_file.GetLocationChecksum());
+  return FindOpenedOatFileFromDexLocation(dex_file.GetLocation());
 }
 
-const OatFile* ClassLinker::FindOpenedOatFileFromDexLocation(const std::string& dex_location,
-                                                             uint32_t dex_location_checksum) {
+const OatFile* ClassLinker::FindOpenedOatFileFromDexLocation(const std::string& dex_location) {
   for (size_t i = 0; i < oat_files_.size(); i++) {
     const OatFile* oat_file = oat_files_[i];
     DCHECK(oat_file != NULL);
     const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location, false);
-    if (oat_dex_file != NULL
-        && oat_dex_file->GetDexFileLocationChecksum() == dex_location_checksum) {
+    if (oat_dex_file != NULL) {
       return oat_file;
     }
   }
@@ -747,7 +730,7 @@
 static const DexFile* FindDexFileInOatLocation(const std::string& dex_location,
                                                uint32_t dex_location_checksum,
                                                const std::string& oat_location) {
-  UniquePtr<OatFile> oat_file(OatFile::Open(oat_location, "", NULL));
+  UniquePtr<OatFile> oat_file(OatFile::Open(oat_location, oat_location, NULL));
   if (oat_file.get() == NULL) {
     return NULL;
   }
@@ -811,22 +794,31 @@
 const DexFile* ClassLinker::FindDexFileInOatFileFromDexLocation(const std::string& dex_location) {
   MutexLock mu(dex_lock_);
 
-  uint32_t dex_location_checksum;
-  if (!DexFile::GetChecksum(dex_location, dex_location_checksum)) {
-    LOG(WARNING) << "Failed to compute checksum: " << dex_location;
-    return NULL;
-  }
-
-  const OatFile* open_oat_file = FindOpenedOatFileFromDexLocation(dex_location, dex_location_checksum);
+  const OatFile* open_oat_file = FindOpenedOatFileFromDexLocation(dex_location);
   if (open_oat_file != NULL) {
     return open_oat_file->GetOatDexFile(dex_location)->OpenDexFile();
   }
 
-  // Look for an existing file first next to dex and in art-cache
+  // Look for an existing file next to dex, assuming its up-to-date if found
   std::string oat_filename(OatFile::DexFilenameToOatFilename(dex_location));
-  const OatFile* oat_file(FindOatFileFromOatLocation(oat_filename));
+  const OatFile* oat_file = FindOatFileFromOatLocation(oat_filename);
   if (oat_file != NULL) {
     const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
+    CHECK(oat_dex_file != NULL) << oat_filename << " " << dex_location;
+    return oat_dex_file->OpenDexFile();
+  }
+  // Look for an existing file in the art-cache, validating the result if found
+  // not found in /foo/bar/baz.oat? try /data/art-cache/foo@bar@baz.oat
+  std::string cache_location(GetArtCacheFilenameOrDie(oat_filename));
+  oat_file = FindOatFileFromOatLocation(cache_location);
+  if (oat_file != NULL) {
+    uint32_t dex_location_checksum;
+    if (!DexFile::GetChecksum(dex_location, dex_location_checksum)) {
+      LOG(WARNING) << "Failed to compute checksum: " << dex_location;
+      return NULL;
+    }
+    const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
+    CHECK(oat_dex_file != NULL) << oat_filename << " " << dex_location;
     if (dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum()) {
       return oat_file->GetOatDexFile(dex_location)->OpenDexFile();
     }
@@ -838,6 +830,8 @@
       PLOG(FATAL) << "Couldn't remove obsolete .oat file " << oat_file->GetLocation();
     }
   }
+  LOG(INFO) << "Failed to open oat file from " << oat_filename << " or " << cache_location << ".";
+
   // Try to generate oat file if it wasn't found or was obsolete.
   std::string oat_cache_filename(GetArtCacheFilenameOrDie(oat_filename));
   return FindOrCreateOatFileForDexLocation(dex_location, oat_cache_filename);
@@ -861,26 +855,10 @@
     return oat_file;
   }
 
-  oat_file = OatFile::Open(oat_location, "", NULL);
+  oat_file = OatFile::Open(oat_location, oat_location, NULL);
   if (oat_file == NULL) {
-    if (oat_location.empty() || oat_location[0] != '/') {
-      LOG(ERROR) << "Failed to open oat file from " << oat_location;
-      return NULL;
-    }
-
-    // not found in /foo/bar/baz.oat? try /data/art-cache/foo@bar@baz.oat
-    std::string cache_location(GetArtCacheFilenameOrDie(oat_location));
-    oat_file = FindOpenedOatFileFromOatLocation(cache_location);
-    if (oat_file != NULL) {
-      return oat_file;
-    }
-    oat_file = OatFile::Open(cache_location, "", NULL);
-    if (oat_file  == NULL) {
-      LOG(INFO) << "Failed to open oat file from " << oat_location << " or " << cache_location << ".";
-      return NULL;
-    }
+    return NULL;
   }
-
   CHECK(oat_file != NULL) << oat_location;
   RegisterOatFileLocked(*oat_file);
   return oat_file;
diff --git a/src/class_linker.h b/src/class_linker.h
index f6b7c15..d90ac1d 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -44,10 +44,11 @@
 class ClassLinker {
  public:
   // Creates the class linker by boot strapping from dex files.
-  static ClassLinker* Create(const std::string& boot_class_path, InternTable* intern_table);
+  static ClassLinker* CreateFromCompiler(const std::vector<const DexFile*>& boot_class_path,
+                                         InternTable* intern_table);
 
-  // Creates the class linker from one or more images.
-  static ClassLinker* Create(InternTable* intern_table);
+  // Creates the class linker from an image.
+  static ClassLinker* CreateFromImage(InternTable* intern_table);
 
   ~ClassLinker();
 
@@ -291,7 +292,7 @@
   explicit ClassLinker(InternTable*);
 
   // Initialize class linker by bootstraping from dex files
-  void Init(const std::string& boot_class_path);
+  void InitFromCompiler(const std::vector<const DexFile*>& boot_class_path);
 
   // Initialize class linker from one or more images.
   void InitFromImage();
@@ -397,8 +398,7 @@
   }
 
   const OatFile* FindOpenedOatFileForDexFile(const DexFile& dex_file);
-  const OatFile* FindOpenedOatFileFromDexLocation(const std::string& dex_location,
-                                                  uint32_t dex_location_checksum);
+  const OatFile* FindOpenedOatFileFromDexLocation(const std::string& dex_location);
   const OatFile* FindOpenedOatFileFromOatLocation(const std::string& oat_location);
 
   Method* CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class);
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 9f63c5e..7741d4d 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -739,7 +739,7 @@
 }
 
 TEST_F(ClassLinkerTest, LibCore) {
-  AssertDexFile(java_lang_dex_file_.get(), NULL);
+  AssertDexFile(java_lang_dex_file_, NULL);
 }
 
 // The first reference array element must be a multiple of 8 bytes from the
diff --git a/src/common_test.h b/src/common_test.h
index 4457cec..f7b9fec 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -125,7 +125,7 @@
   file.reset();
 
   // read dex file
-  const DexFile* dex_file = DexFile::Open(location, "");
+  const DexFile* dex_file = DexFile::Open(location, location);
   CHECK(dex_file != NULL);
   return dex_file;
 }
@@ -137,7 +137,7 @@
     filename_ += "/TmpFile-XXXXXX";
     fd_ = mkstemp(&filename_[0]);
     CHECK_NE(-1, fd_);
-    file_.reset(OS::FileFromFd(GetFilename(), fd_));
+    file_.reset(OS::FileFromFd(GetFilename().c_str(), fd_));
   }
 
   ~ScratchFile() {
@@ -147,8 +147,8 @@
     CHECK_EQ(0, close_result);
   }
 
-  const char* GetFilename() const {
-    return filename_.c_str();
+  const std::string& GetFilename() const {
+    return filename_;
   }
 
   File* GetFile() const {
@@ -301,18 +301,15 @@
     int mkdir_result = mkdir(art_cache_.c_str(), 0700);
     ASSERT_EQ(mkdir_result, 0);
 
-    java_lang_dex_file_.reset(DexFile::Open(GetLibCoreDexFileName(), ""));
-
-    std::string boot_class_path;
-    boot_class_path += "-Xbootclasspath:";
-    boot_class_path += GetLibCoreDexFileName();
+    java_lang_dex_file_ = DexFile::Open(GetLibCoreDexFileName(), GetLibCoreDexFileName());
+    boot_class_path_.push_back(java_lang_dex_file_);
 
     std::string min_heap_string(StringPrintf("-Xms%zdm", Heap::kInitialSize / MB));
     std::string max_heap_string(StringPrintf("-Xmx%zdm", Heap::kMaximumSize / MB));
 
     Runtime::Options options;
     options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
-    options.push_back(std::make_pair(boot_class_path.c_str(), reinterpret_cast<void*>(NULL)));
+    options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
     options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL)));
     options.push_back(std::make_pair(min_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
     options.push_back(std::make_pair(max_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
@@ -409,7 +406,7 @@
     filename += "/data/nativetest/art/art-test-dex-";
     filename += name;
     filename += ".jar";
-    const DexFile* dex_file = DexFile::Open(filename, "");
+    const DexFile* dex_file = DexFile::Open(filename, filename);
     CHECK(dex_file != NULL) << "Failed to open " << filename;
     opened_dex_files_.push_back(dex_file);
     return dex_file;
@@ -476,7 +473,7 @@
   bool is_host_;
   std::string android_data_;
   std::string art_cache_;
-  UniquePtr<const DexFile> java_lang_dex_file_;
+  const DexFile* java_lang_dex_file_;  // owned by runtime_
   std::vector<const DexFile*> boot_class_path_;
   UniquePtr<Runtime> runtime_;
   // Owned by the runtime
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 76a39a4..a7c2691 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -88,7 +88,7 @@
   CompileAll(NULL);
 
   // All libcore references should resolve
-  const DexFile* dex = java_lang_dex_file_.get();
+  const DexFile* dex = java_lang_dex_file_;
   DexCache* dex_cache = class_linker_->FindDexCache(*dex);
   EXPECT_EQ(dex->NumStringIds(), dex_cache->NumStrings());
   for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
@@ -139,6 +139,7 @@
 }
 
 TEST_F(CompilerTest, AbstractMethodErrorStub) {
+  CompileVirtualMethod(NULL, "java.lang.Class", "isFinalizable", "()Z");
   CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V");
 
   SirtRef<ClassLoader> class_loader(LoadDex("AbstractMethod"));
diff --git a/src/dalvik_system_DexFile.cc b/src/dalvik_system_DexFile.cc
index 713639f..f6568a7 100644
--- a/src/dalvik_system_DexFile.cc
+++ b/src/dalvik_system_DexFile.cc
@@ -185,13 +185,18 @@
     }
   }
 
-  uint32_t location_checksum;
-  if (!DexFile::GetChecksum(filename.c_str(), location_checksum)) {
-    return JNI_TRUE;
+  // If we have an oat file next to the dex file, assume up-to-date.
+  // A user build looks like this, and it will have no classes.dex in
+  // the input for checksum validation.
+  std::string oat_filename(OatFile::DexFilenameToOatFilename(filename.c_str()));
+  const OatFile* oat_file = class_linker->FindOatFileFromOatLocation(oat_filename);
+  if (oat_file != NULL && oat_file->GetOatDexFile(filename.c_str()) != NULL) {
+    return JNI_FALSE;
   }
 
-  std::string oat_filename(OatFile::DexFilenameToOatFilename(filename.c_str()));
-  const OatFile* oat_file(class_linker->FindOatFileFromOatLocation(oat_filename));
+  // Check if we have an oat file in the cache
+  std::string cache_location(GetArtCacheFilenameOrDie(oat_filename));
+  oat_file = class_linker->FindOatFileFromOatLocation(cache_location);
   if (oat_file == NULL) {
     return JNI_TRUE;
   }
@@ -201,6 +206,11 @@
     return JNI_TRUE;
   }
 
+  uint32_t location_checksum;
+  if (!DexFile::GetChecksum(filename.c_str(), location_checksum)) {
+    return JNI_TRUE;
+  }
+
   if (location_checksum != oat_dex_file->GetDexFileLocationChecksum()) {
     return JNI_TRUE;
   }
diff --git a/src/dalvik_system_VMRuntime.cc b/src/dalvik_system_VMRuntime.cc
index b953248..6f9480d 100644
--- a/src/dalvik_system_VMRuntime.cc
+++ b/src/dalvik_system_VMRuntime.cc
@@ -109,11 +109,11 @@
 }
 
 jstring VMRuntime_bootClassPath(JNIEnv* env, jobject) {
-  return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetBootClassPath()));
+  return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetBootClassPathString()));
 }
 
 jstring VMRuntime_classPath(JNIEnv* env, jobject) {
-  return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetClassPath()));
+  return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetClassPathString()));
 }
 
 jstring VMRuntime_vmVersion(JNIEnv* env, jobject) {
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index a27b76e..40e27a9 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -32,6 +32,7 @@
 #include "object_utils.h"
 #include "os.h"
 #include "runtime.h"
+#include "stl_util.h"
 #include "stringpiece.h"
 #include "timing_logger.h"
 #include "zip_archive.h"
@@ -52,18 +53,18 @@
           "      Example: --zip-fd=5\n"
           "\n");
   fprintf(stderr,
-          "  --zip-name=<zip-name>: specifies a symbolic name for the file corresponding\n"
+          "  --zip-location=<zip-location>: specifies a symbolic name for the file corresponding\n"
           "      to the file descriptor specified by --zip-fd.\n"
-          "      Example: --zip-name=/system/app/Calculator.apk\n"
+          "      Example: --zip-location=/system/app/Calculator.apk\n"
           "\n");
   fprintf(stderr,
           "  --oat-file=<file.oat>: specifies the required oat filename.\n"
           "      Example: --oat-file=/system/framework/boot.oat\n"
           "\n");
   fprintf(stderr,
-          "  --oat-name=<oat-name>: specifies a symbolic name for the file corresponding\n"
+          "  --oat-location=<oat-name>: specifies a symbolic name for the file corresponding\n"
           "      to the file descriptor specified by --oat-fd.\n"
-          "      Example: --oat-name=/data/art-cache/system@app@Calculator.apk.oat\n"
+          "      Example: --oat-location=/data/art-cache/system@app@Calculator.apk.oat\n"
           "\n");
   fprintf(stderr,
           "  --image=<file.art>: specifies the output image filename.\n"
@@ -191,7 +192,7 @@
     if (!boot_image_option.empty()) {
       ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
       std::vector<const DexFile*> class_path_files(dex_files);
-      OpenClassPathFiles(runtime_->GetClassPath(), class_path_files);
+      OpenClassPathFiles(runtime_->GetClassPathString(), class_path_files);
       for (size_t i = 0; i < class_path_files.size(); i++) {
         class_linker->RegisterDexFile(*class_path_files[i]);
       }
@@ -208,11 +209,11 @@
     return true;
   }
 
-  bool CreateImageFile(const char* image_filename,
+  bool CreateImageFile(const std::string& image_filename,
                        uintptr_t image_base,
                        const std::set<std::string>* image_classes,
                        const std::string& oat_filename,
-                       const std::string& host_prefix) {
+                       const std::string& oat_location) {
     // If we have an existing boot image, position new space after its oat file
     if (Heap::GetSpaces().size() > 1) {
       ImageSpace* last_image_space = NULL;
@@ -230,7 +231,7 @@
     }
 
     ImageWriter image_writer(image_classes);
-    if (!image_writer.Write(image_filename, image_base, oat_filename, host_prefix)) {
+    if (!image_writer.Write(image_filename, image_base, oat_filename, oat_location)) {
       LOG(ERROR) << "Failed to create image file " << image_filename;
       return false;
     }
@@ -342,7 +343,7 @@
       if (DexFilesContains(dex_files, parsed[i])) {
         continue;
       }
-      const DexFile* dex_file = DexFile::Open(parsed[i], Runtime::Current()->GetHostPrefix());
+      const DexFile* dex_file = DexFile::Open(parsed[i], parsed[i]);
       if (dex_file == NULL) {
         LOG(WARNING) << "Failed to open dex file " << parsed[i];
       } else {
@@ -381,11 +382,12 @@
 }
 
 void OpenDexFiles(const std::vector<const char*>& dex_filenames,
-                  std::vector<const DexFile*>& dex_files,
-                  const std::string& strip_location_prefix) {
+                  const std::vector<const char*>& dex_locations,
+                  std::vector<const DexFile*>& dex_files) {
   for (size_t i = 0; i < dex_filenames.size(); i++) {
     const char* dex_filename = dex_filenames[i];
-    const DexFile* dex_file = DexFile::Open(dex_filename, strip_location_prefix);
+    const char* dex_location = dex_locations[i];
+    const DexFile* dex_file = DexFile::Open(dex_filename, dex_location);
     if (dex_file == NULL) {
       LOG(WARNING) << "could not open .dex from file " << dex_filename;
     } else {
@@ -406,13 +408,14 @@
   }
 
   std::vector<const char*> dex_filenames;
+  std::vector<const char*> dex_locations;
   int zip_fd = -1;
-  std::string zip_name;
+  std::string zip_location;
   std::string oat_filename;
+  std::string oat_location;
   int oat_fd = -1;
-  std::string oat_name;
-  const char* image_filename = NULL;
   const char* image_classes_filename = NULL;
+  std::string image_filename;
   std::string boot_image_filename;
   uintptr_t image_base = 0;
   std::string host_prefix;
@@ -427,14 +430,16 @@
     }
     if (option.starts_with("--dex-file=")) {
       dex_filenames.push_back(option.substr(strlen("--dex-file=")).data());
+    } else if (option.starts_with("--dex-location=")) {
+      dex_locations.push_back(option.substr(strlen("--dex-location=")).data());
     } else if (option.starts_with("--zip-fd=")) {
       const char* zip_fd_str = option.substr(strlen("--zip-fd=")).data();
       if (!ParseInt(zip_fd_str, &zip_fd)) {
         fprintf(stderr, "could not parse --zip-fd argument '%s' as an integer\n", zip_fd_str);
         usage();
       }
-    } else if (option.starts_with("--zip-name=")) {
-      zip_name = option.substr(strlen("--zip-name=")).data();
+    } else if (option.starts_with("--zip-location=")) {
+      zip_location = option.substr(strlen("--zip-location=")).data();
     } else if (option.starts_with("--oat-file=")) {
       oat_filename = option.substr(strlen("--oat-file=")).data();
     } else if (option.starts_with("--oat-fd=")) {
@@ -449,8 +454,8 @@
         fprintf(stderr, "could not parse -j argument '%s' as an integer\n", thread_count_str);
         usage();
       }
-    } else if (option.starts_with("--oat-name=")) {
-      oat_name = option.substr(strlen("--oat-name=")).data();
+    } else if (option.starts_with("--oat-location=")) {
+      oat_location = option.substr(strlen("--oat-location=")).data();
     } else if (option.starts_with("--image=")) {
       image_filename = option.substr(strlen("--image=")).data();
     } else if (option.starts_with("--image-classes=")) {
@@ -497,17 +502,7 @@
     return EXIT_FAILURE;
   }
 
-  if (!oat_filename.empty() && !oat_name.empty()) {
-    fprintf(stderr, "--oat-file should not be used with --oat-name\n");
-    return EXIT_FAILURE;
-  }
-
-  if (oat_fd != -1 && oat_name.empty()) {
-    fprintf(stderr, "--oat-name should be supplied with --oat-fd\n");
-    return EXIT_FAILURE;
-  }
-
-  if (oat_fd != -1 && image_filename != NULL) {
+  if (oat_fd != -1 && !image_filename.empty()) {
     fprintf(stderr, "--oat-fd should not be used with --image\n");
     return EXIT_FAILURE;
   }
@@ -519,7 +514,7 @@
     }
   }
 
-  bool image = (image_filename != NULL);
+  bool image = (!image_filename.empty());
   if (!image && boot_image_filename.empty()) {
     if (host_prefix.empty()) {
       boot_image_filename += GetAndroidRoot();
@@ -530,7 +525,11 @@
     boot_image_filename += "/framework/boot.art";
   }
   std::string boot_image_option;
-  if (boot_image_filename != NULL) {
+  if (!boot_image_filename.empty()) {
+    if (!OS::FileExists(boot_image_filename.c_str())) {
+      fprintf(stderr, "Failed to find boot image file %s\n", boot_image_filename.c_str());
+      return EXIT_FAILURE;
+    }
     boot_image_option += "-Ximage:";
     boot_image_option += boot_image_filename;
   }
@@ -555,13 +554,22 @@
     return EXIT_FAILURE;
   }
 
-  if (!dex_filenames.empty() && !zip_name.empty()) {
-    fprintf(stderr, "--dex-file should not be used with --zip-name\n");
+  if (!dex_filenames.empty() && !zip_location.empty()) {
+    fprintf(stderr, "--dex-file should not be used with --zip-location\n");
     return EXIT_FAILURE;
   }
 
-  if (zip_fd != -1 && zip_name.empty()) {
-    fprintf(stderr, "--zip-name should be supplied with --zip-fd\n");
+  if (dex_locations.empty()) {
+    for (size_t i = 0; i < dex_filenames.size(); i++) {
+      dex_locations.push_back(dex_filenames[i]);
+    }
+  } else if (dex_locations.size() != dex_filenames.size()) {
+    fprintf(stderr, "--dex-location arguments do not match --dex-file arguments\n");
+    return EXIT_FAILURE;
+  }
+
+  if (zip_fd != -1 && zip_location.empty()) {
+    fprintf(stderr, "--zip-location should be supplied with --zip-fd\n");
     return EXIT_FAILURE;
   }
 
@@ -576,28 +584,25 @@
   UniquePtr<File> oat_file;
   if (!oat_filename.empty()) {
     oat_file.reset(OS::OpenFile(oat_filename.c_str(), true));
-    oat_name = oat_filename;
+    if (oat_location.empty()) {
+      oat_location = oat_filename;
+    }
   } else {
-    oat_file.reset(OS::FileFromFd(oat_name.c_str(), oat_fd));
+    oat_file.reset(OS::FileFromFd(oat_location.c_str(), oat_fd));
   }
   if (oat_file.get() == NULL) {
-    PLOG(ERROR) << "Unable to create oat file: " << oat_name;
+    PLOG(ERROR) << "Unable to create oat file: " << oat_location;
     return EXIT_FAILURE;
   }
 
-  LOG(INFO) << "dex2oat: " << oat_name;
+  LOG(INFO) << "dex2oat: " << oat_location;
 
   Runtime::Options options;
   options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
-  std::string boot_class_path_string;
+  std::vector<const DexFile*> boot_class_path;
   if (boot_image_option.empty()) {
-    boot_class_path_string += "-Xbootclasspath:";
-    for (size_t i = 0; i < dex_filenames.size()-1; i++) {
-      boot_class_path_string += dex_filenames[i];
-      boot_class_path_string += ":";
-    }
-    boot_class_path_string += dex_filenames[dex_filenames.size()-1];
-    options.push_back(std::make_pair(boot_class_path_string.c_str(), reinterpret_cast<void*>(NULL)));
+    OpenDexFiles(dex_filenames, dex_locations, boot_class_path);
+    options.push_back(std::make_pair("bootclasspath", &boot_class_path));
   } else {
     options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
   }
@@ -627,17 +632,17 @@
     if (dex_filenames.empty()) {
       UniquePtr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(zip_fd));
       if (zip_archive.get() == NULL) {
-        LOG(ERROR) << "Failed to zip from file descriptor for " << zip_name;
+        LOG(ERROR) << "Failed to zip from file descriptor for " << zip_location;
         return EXIT_FAILURE;
       }
-      const DexFile* dex_file = DexFile::Open(*zip_archive.get(), zip_name);
+      const DexFile* dex_file = DexFile::Open(*zip_archive.get(), zip_location);
       if (dex_file == NULL) {
-        LOG(ERROR) << "Failed to open dex from file descriptor for zip file: " << zip_name;
+        LOG(ERROR) << "Failed to open dex from file descriptor for zip file: " << zip_location;
         return EXIT_FAILURE;
       }
       dex_files.push_back(dex_file);
     } else {
-      OpenDexFiles(dex_filenames, dex_files, host_prefix);
+      OpenDexFiles(dex_filenames, dex_locations, dex_files);
     }
   }
 
@@ -646,12 +651,12 @@
                               oat_file.get(),
                               image,
                               image_classes.get())) {
-    LOG(ERROR) << "Failed to create oat file: " << oat_name;
+    LOG(ERROR) << "Failed to create oat file: " << oat_location;
     return EXIT_FAILURE;
   }
 
   if (!image) {
-    LOG(INFO) << "Oat file written successfully: " << oat_name;
+    LOG(INFO) << "Oat file written successfully: " << oat_location;
     return EXIT_SUCCESS;
   }
 
@@ -659,7 +664,7 @@
                                 image_base,
                                 image_classes.get(),
                                 oat_filename,
-                                host_prefix)) {
+                                oat_location)) {
     return EXIT_FAILURE;
   }
 
diff --git a/src/dex_cache_test.cc b/src/dex_cache_test.cc
index ce79de1..c8dbc7c 100644
--- a/src/dex_cache_test.cc
+++ b/src/dex_cache_test.cc
@@ -27,7 +27,7 @@
 class DexCacheTest : public CommonTest {};
 
 TEST_F(DexCacheTest, Open) {
-  SirtRef<DexCache> dex_cache(class_linker_->AllocDexCache(*java_lang_dex_file_.get()));
+  SirtRef<DexCache> dex_cache(class_linker_->AllocDexCache(*java_lang_dex_file_));
   ASSERT_TRUE(dex_cache.get() != NULL);
 
   EXPECT_EQ(java_lang_dex_file_->NumStringIds(), dex_cache->NumStrings());
diff --git a/src/dex_file.cc b/src/dex_file.cc
index c574d89..2a59ee3 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -85,14 +85,14 @@
 }
 
 const DexFile* DexFile::Open(const std::string& filename,
-                             const std::string& strip_location_prefix) {
+                             const std::string& location) {
   if (IsValidZipFilename(filename)) {
-    return DexFile::OpenZip(filename, strip_location_prefix);
+    return DexFile::OpenZip(filename, location);
   }
   if (!IsValidDexFilename(filename)) {
     LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'";
   }
-  return DexFile::OpenFile(filename, strip_location_prefix, true);
+  return DexFile::OpenFile(filename, location, true);
 }
 
 void DexFile::ChangePermissions(int prot) const {
@@ -101,25 +101,10 @@
   }
 }
 
-const std::string StripLocationPrefix(const std::string& original_location,
-                                      const std::string& strip_location_prefix) {
-  StringPiece location = original_location;
-  if (!location.starts_with(strip_location_prefix)) {
-    LOG(ERROR) << location << " does not start with " << strip_location_prefix;
-    return "";
-  }
-  location.remove_prefix(strip_location_prefix.size());
-  return location.ToString();
-}
-
 const DexFile* DexFile::OpenFile(const std::string& filename,
-                                 const std::string& strip_location_prefix,
+                                 const std::string& location,
                                  bool verify) {
-  std::string location(StripLocationPrefix(filename, strip_location_prefix));
-  if (location.empty()) {
-    return NULL;
-  }
-
+  CHECK(!location.empty()) << filename;
   int fd = open(filename.c_str(), O_RDONLY);  // TODO: scoped_fd
   if (fd == -1) {
     PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
@@ -170,12 +155,7 @@
 
 // Open classes.dex from within a .zip, .jar, .apk, ...
 const DexFile* DexFile::OpenZip(const std::string& filename,
-                                const std::string& strip_location_prefix) {
-  std::string location(StripLocationPrefix(filename, strip_location_prefix));
-  if (location.empty()) {
-    return NULL;
-  }
-
+                                const std::string& location) {
   UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
   if (zip_archive.get() == NULL) {
     LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
@@ -185,6 +165,7 @@
 }
 
 const DexFile* DexFile::Open(const ZipArchive& zip_archive, const std::string& location) {
+  CHECK(!location.empty());
   UniquePtr<ZipEntry> zip_entry(zip_archive.Find(kClassesDex));
   if (zip_entry.get() == NULL) {
     LOG(ERROR) << "Failed to find classes.dex within " << location;
diff --git a/src/dex_file.h b/src/dex_file.h
index 5d63408..1f87bca 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -322,7 +322,7 @@
 
   // Opens .dex file, guessing the container format based on file extension
   static const DexFile* Open(const std::string& filename,
-                             const std::string& strip_location_prefix);
+                             const std::string& location);
 
   // Opens .dex file, backed by existing memory
   static const DexFile* Open(const uint8_t* base, size_t size,
@@ -773,12 +773,12 @@
 
   // Opens a .dex file
   static const DexFile* OpenFile(const std::string& filename,
-                                 const std::string& strip_location_prefix,
+                                 const std::string& location,
                                  bool verify);
 
   // Opens a dex file from within a .jar, .zip, or .apk file
   static const DexFile* OpenZip(const std::string& filename,
-                                const std::string& strip_location_prefix);
+                                const std::string& location);
 
   // Opens a .dex file at the given address backed by a MemMap
   static const DexFile* OpenMemory(const std::string& location,
diff --git a/src/dex_verifier_test.cc b/src/dex_verifier_test.cc
index 51fb1bc..9106b76 100644
--- a/src/dex_verifier_test.cc
+++ b/src/dex_verifier_test.cc
@@ -50,7 +50,7 @@
 };
 
 TEST_F(DexVerifierTest, LibCore) {
-  VerifyDexFile(java_lang_dex_file_.get(), NULL);
+  VerifyDexFile(java_lang_dex_file_, NULL);
 }
 
 TEST_F(DexVerifierTest, IntMath) {
diff --git a/src/heap.cc b/src/heap.cc
index 3a3ee5a..ad20f9c 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -84,7 +84,7 @@
 }
 
 bool GenerateImage(const std::string image_file_name) {
-  const std::string boot_class_path_string = Runtime::Current()->GetBootClassPath();
+  const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString());
   std::vector<std::string> boot_class_path;
   Split(boot_class_path_string, ':', boot_class_path);
 
diff --git a/src/image_test.cc b/src/image_test.cc
index 97d37c5..fb87a49 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -33,7 +33,7 @@
 TEST_F(ImageTest, WriteRead) {
   ScratchFile tmp_oat;
   std::vector<const DexFile*> dex_files;
-  dex_files.push_back(java_lang_dex_file_.get());
+  dex_files.push_back(java_lang_dex_file_);
   bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, dex_files, *compiler_.get());
   ASSERT_TRUE(success_oat);
 
@@ -49,11 +49,11 @@
   ScratchFile tmp_image;
   const uintptr_t requested_image_base = 0x60000000;
   bool success_image = writer.Write(tmp_image.GetFilename(), requested_image_base,
-                                    std::string(tmp_oat.GetFilename()), "");
+                                    tmp_oat.GetFilename(), tmp_oat.GetFilename());
   ASSERT_TRUE(success_image);
 
   {
-    UniquePtr<File> file(OS::OpenFile(tmp_image.GetFilename(), false));
+    UniquePtr<File> file(OS::OpenFile(tmp_image.GetFilename().c_str(), false));
     ASSERT_TRUE(file.get() != NULL);
     ImageHeader image_header;
     file->ReadFully(&image_header, sizeof(image_header));
@@ -68,12 +68,9 @@
 
   // tear down old runtime before making a new one, clearing out misc state
   delete runtime_.release();
+  java_lang_dex_file_ = NULL;
 
-  // don't reuse java_lang_dex_file_ so we make sure we don't get
-  // lucky by pointers that happen to work referencing the earlier
-  // dex.
-  delete java_lang_dex_file_.release();
-  UniquePtr<const DexFile> dex(DexFile::Open(GetLibCoreDexFileName(), ""));
+  UniquePtr<const DexFile> dex(DexFile::Open(GetLibCoreDexFileName(), GetLibCoreDexFileName()));
   ASSERT_TRUE(dex.get() != NULL);
 
   Runtime::Options options;
diff --git a/src/image_writer.cc b/src/image_writer.cc
index f92989d..ffe4ec3 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -41,11 +41,11 @@
 
 std::map<const Object*, size_t> ImageWriter::offsets_;
 
-bool ImageWriter::Write(const char* image_filename,
+bool ImageWriter::Write(const std::string& image_filename,
                         uintptr_t image_begin,
                         const std::string& oat_filename,
-                        const std::string& strip_location_prefix) {
-  CHECK(image_filename != NULL);
+                        const std::string& oat_location) {
+  CHECK(!image_filename.empty());
 
   CHECK_NE(image_begin, 0U);
   image_begin_ = reinterpret_cast<byte*>(image_begin);
@@ -65,7 +65,7 @@
     }
   }
 
-  oat_file_.reset(OatFile::Open(oat_filename, strip_location_prefix, NULL));
+  oat_file_.reset(OatFile::Open(oat_filename, oat_location, NULL));
   if (oat_file_.get() == NULL) {
     LOG(ERROR) << "Failed to open oat file " << oat_filename;
     return false;
@@ -85,7 +85,7 @@
   CalculateNewObjectOffsets();
   CopyAndFixupObjects();
 
-  UniquePtr<File> file(OS::OpenFile(image_filename, true));
+  UniquePtr<File> file(OS::OpenFile(image_filename.c_str(), true));
   if (file.get() == NULL) {
     LOG(ERROR) << "Failed to open image file " << image_filename;
     return false;
diff --git a/src/image_writer.h b/src/image_writer.h
index 5e0ed01..74a3f94 100644
--- a/src/image_writer.h
+++ b/src/image_writer.h
@@ -43,10 +43,10 @@
 
   ~ImageWriter() {}
 
-  bool Write(const char* image_filename,
+  bool Write(const std::string& image_filename,
              uintptr_t image_begin,
              const std::string& oat_filename,
-             const std::string& strip_location_prefix);
+             const std::string& oat_location);
  private:
 
   bool AllocMemory();
diff --git a/src/oat_file.cc b/src/oat_file.cc
index cf8bafe..26314b1 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -32,19 +32,14 @@
 }
 
 OatFile* OatFile::Open(const std::string& filename,
-                       const std::string& strip_location_prefix,
+                       const std::string& location,
                        byte* requested_base) {
-  StringPiece location(filename);
-  if (!location.starts_with(strip_location_prefix)) {
-    LOG(ERROR) << filename << " does not start with " << strip_location_prefix;
-    return NULL;
-  }
-  location.remove_prefix(strip_location_prefix.size());
+  CHECK(!location.empty()) << filename;
   UniquePtr<File> file(OS::OpenFile(filename.c_str(), false));
   if (file.get() == NULL) {
     return false;
   }
-  return Open(*file.get(), location.ToString(), requested_base);
+  return Open(*file.get(), location, requested_base);
 }
 
 OatFile* OatFile::Open(File& file,
@@ -58,7 +53,9 @@
   return oat_file.release();
 }
 
-OatFile::OatFile(const std::string& filename) : location_(filename) {}
+OatFile::OatFile(const std::string& location) : location_(location) {
+  CHECK(!location_.empty());
+}
 
 OatFile::~OatFile() {
   STLDeleteValues(&oat_dex_files_);
diff --git a/src/oat_file.h b/src/oat_file.h
index 2895d74..83560e8 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -36,7 +36,7 @@
   // Open an oat file. Returns NULL on failure.  Requested base can
   // optionally be used to request where the file should be loaded.
   static OatFile* Open(const std::string& filename,
-                       const std::string& strip_location_prefix,
+                       const std::string& location,
                        byte* requested_base);
 
   // Open an oat file from an already opened File with the given location.
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 7c837d4..b27595e 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -40,23 +40,23 @@
   if (compile) {  // OatWriter strips the code, regenerate to compare
     compiler_->CompileAll(class_loader.get(), class_linker->GetBootClassPath());
   }
-  UniquePtr<OatFile> oat_file(OatFile::Open(std::string(tmp.GetFilename()), "", NULL));
+  UniquePtr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), tmp.GetFilename(), NULL));
   ASSERT_TRUE(oat_file.get() != NULL);
   const OatHeader& oat_header = oat_file->GetOatHeader();
   ASSERT_EQ(1U, oat_header.GetDexFileCount());
 
-  const DexFile& dex_file = *java_lang_dex_file_.get();
-  const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation());
-  CHECK_EQ(dex_file.GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
-  for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
-    const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
-    const byte* class_data = dex_file.GetClassData(class_def);
+  const DexFile* dex_file = java_lang_dex_file_;
+  const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file->GetLocation());
+  CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
+  for (size_t i = 0; i < dex_file->NumClassDefs(); i++) {
+    const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
+    const byte* class_data = dex_file->GetClassData(class_def);
     size_t num_virtual_methods =0;
     if (class_data != NULL) {
-      ClassDataItemIterator it(dex_file, class_data);
+      ClassDataItemIterator it(*dex_file, class_data);
       num_virtual_methods = it.NumVirtualMethods();
     }
-    const char* descriptor = dex_file.GetClassDescriptor(class_def);
+    const char* descriptor = dex_file->GetClassDescriptor(class_def);
 
     UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(i));
 
@@ -67,7 +67,7 @@
       Method* method = klass->GetDirectMethod(i);
       const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
       const CompiledMethod* compiled_method =
-          compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file,
+          compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file,
                                                                  method->GetDexMethodIndex()));
 
       if (compiled_method == NULL) {
@@ -94,7 +94,7 @@
       Method* method = klass->GetVirtualMethod(i);
       const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
       const CompiledMethod* compiled_method =
-          compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file,
+          compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file,
                                                                  method->GetDexMethodIndex()));
 
       if (compiled_method == NULL) {
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 4ea2af1..1b54b24 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -81,7 +81,6 @@
 class OatDump {
  public:
   static void Dump(const std::string& oat_filename,
-                   const std::string& host_prefix,
                    std::ostream& os,
                    const OatFile& oat_file) {
     const OatHeader& oat_header = oat_file.GetOatHeader();
@@ -110,26 +109,19 @@
     for (size_t i = 0; i < oat_dex_files.size(); i++) {
       const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
       CHECK(oat_dex_file != NULL);
-      DumpOatDexFile(host_prefix, os, oat_file, *oat_dex_file);
+      DumpOatDexFile(os, oat_file, *oat_dex_file);
     }
   }
 
  private:
-  static void DumpOatDexFile(const std::string& host_prefix,
-                             std::ostream& os,
+  static void DumpOatDexFile(std::ostream& os,
                              const OatFile& oat_file,
                              const OatFile::OatDexFile& oat_dex_file) {
     os << "OAT DEX FILE:\n";
-    std::string dex_file_location(oat_dex_file.GetDexFileLocation());
-    os << "location: " << dex_file_location;
-    if (!host_prefix.empty()) {
-      dex_file_location = host_prefix + dex_file_location;
-      os << " (" << dex_file_location << ")";
-    }
-    os << "\n";
+    os << StringPrintf("location: %s\n", oat_dex_file.GetDexFileLocation().c_str());
     os << StringPrintf("checksum: %08x\n", oat_dex_file.GetDexFileLocationChecksum());
-    const DexFile* dex_file = DexFile::Open(dex_file_location, "");
-    if (dex_file == NULL) {
+    UniquePtr<const DexFile> dex_file(oat_dex_file.OpenDexFile());
+    if (dex_file.get() == NULL) {
       os << "NOT FOUND\n\n";
       return;
     }
@@ -140,7 +132,7 @@
       CHECK(oat_class.get() != NULL);
       os << StringPrintf("%zd: %s (type_idx=%d) (", class_def_index, descriptor, class_def.class_idx_)
          << oat_class->GetStatus() << ")\n";
-      DumpOatClass(os, oat_file, *oat_class.get(), *dex_file, class_def);
+      DumpOatClass(os, oat_file, *oat_class.get(), *(dex_file.get()), class_def);
     }
 
     os << std::flush;
@@ -291,7 +283,7 @@
     os << "\n";
     os << std::flush;
 
-    OatDump::Dump(oat_location, host_prefix, os, *oat_file);
+    OatDump::Dump(oat_location, os, *oat_file);
   }
 
  private:
@@ -561,12 +553,12 @@
   }
 
   if (oat_filename != NULL) {
-    const OatFile* oat_file = OatFile::Open(oat_filename, "", NULL);
+    const OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, NULL);
     if (oat_file == NULL) {
       fprintf(stderr, "Failed to open oat file from %s\n", oat_filename);
       return EXIT_FAILURE;
     }
-    OatDump::Dump(oat_filename, host_prefix, *os, *oat_file);
+    OatDump::Dump(oat_filename, *os, *oat_file);
     return EXIT_SUCCESS;
   }
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 31b6539..537aadb 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -261,13 +261,13 @@
 
 Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) {
   UniquePtr<ParsedOptions> parsed(new ParsedOptions());
-  const char* boot_class_path = getenv("BOOTCLASSPATH");
-  if (boot_class_path != NULL) {
-    parsed->boot_class_path_ = boot_class_path;
+  const char* boot_class_path_string = getenv("BOOTCLASSPATH");
+  if (boot_class_path_string != NULL) {
+    parsed->boot_class_path_string_ = boot_class_path_string;
   }
-  const char* class_path = getenv("CLASSPATH");
-  if (class_path != NULL) {
-    parsed->class_path_ = class_path;
+  const char* class_path_string = getenv("CLASSPATH");
+  if (class_path_string != NULL) {
+    parsed->class_path_string_ = class_path_string;
   }
 #ifdef NDEBUG
   // -Xcheck:jni is off by default for regular builds...
@@ -299,7 +299,7 @@
       LOG(INFO) << "option[" << i << "]=" << option;
     }
     if (StartsWith(option, "-Xbootclasspath:")) {
-      parsed->boot_class_path_ = option.substr(strlen("-Xbootclasspath:"));
+      parsed->boot_class_path_string_ = option.substr(strlen("-Xbootclasspath:")).data();
     } else if (option == "-classpath" || option == "-cp") {
       // TODO: support -Djava.class.path
       i++;
@@ -308,9 +308,13 @@
         LOG(FATAL) << "Missing required class path value for " << option;
         return NULL;
       }
-      parsed->class_path_ = options[i].first;
+      const StringPiece& value = options[i].first;
+      parsed->class_path_string_ = value.data();
+    } else if (option == "bootclasspath") {
+      parsed->boot_class_path_
+          = reinterpret_cast<const std::vector<const DexFile*>*>(options[i].second);
     } else if (StartsWith(option, "-Ximage:")) {
-      parsed->image_ = option.substr(strlen("-Ximage:"));
+      parsed->image_ = option.substr(strlen("-Ximage:")).data();
     } else if (StartsWith(option, "-Xcheck:jni")) {
       parsed->check_jni_ = true;
     } else if (StartsWith(option, "-Xrunjdwp:") || StartsWith(option, "-agentlib:jdwp=")) {
@@ -582,8 +586,8 @@
   Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_);
 
   host_prefix_ = options->host_prefix_;
-  boot_class_path_ = options->boot_class_path_;
-  class_path_ = options->class_path_;
+  boot_class_path_string_ = options->boot_class_path_string_;
+  class_path_string_ = options->class_path_string_;
   properties_ = options->properties_;
 
   is_compiler_ = options->is_compiler_;
@@ -619,9 +623,14 @@
   Thread::Current()->SetState(Thread::kRunnable);
 
   CHECK_GE(Heap::GetSpaces().size(), 1U);
-  class_linker_ = ((Heap::GetSpaces()[0]->IsImageSpace())
-                   ? ClassLinker::Create(intern_table_)
-                   : ClassLinker::Create(options->boot_class_path_, intern_table_));
+  if (Heap::GetSpaces()[0]->IsImageSpace()) {
+    class_linker_ = ClassLinker::CreateFromImage(intern_table_);
+  } else {
+    CHECK(options->boot_class_path_ != NULL);
+    CHECK_NE(options->boot_class_path_->size(), 0U);
+    class_linker_ = ClassLinker::CreateFromCompiler(*options->boot_class_path_, intern_table_);
+  }
+  CHECK(class_linker_ != NULL);
 
   VLOG(startup) << "Runtime::Init exiting";
   return true;
diff --git a/src/runtime.h b/src/runtime.h
index b284b46..af44948 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -60,8 +60,9 @@
     // returns null if problem parsing and ignore_unrecognized is false
     static ParsedOptions* Create(const Options& options, bool ignore_unrecognized);
 
-    std::string boot_class_path_;
-    std::string class_path_;
+    const std::vector<const DexFile*>* boot_class_path_;
+    std::string boot_class_path_string_;
+    std::string class_path_string_;
     std::string host_prefix_;
     std::string image_;
     bool check_jni_;
@@ -131,18 +132,18 @@
 
   ~Runtime();
 
-  const std::string& GetBootClassPath() const {
-    return boot_class_path_;
+  const std::string& GetBootClassPathString() const {
+    return boot_class_path_string_;
+  }
+
+  const std::string& GetClassPathString() const {
+    return class_path_string_;
   }
 
   ClassLinker* GetClassLinker() const {
     return class_linker_;
   }
 
-  const std::string& GetClassPath() const {
-    return class_path_;
-  }
-
   size_t GetDefaultStackSize() const {
     return default_stack_size_;
   }
@@ -255,8 +256,8 @@
   // files contain the expected target path.
   std::string host_prefix_;
 
-  std::string boot_class_path_;
-  std::string class_path_;
+  std::string boot_class_path_string_;
+  std::string class_path_string_;
   std::vector<std::string> properties_;
 
   // The default stack size for managed threads created by the runtime.
diff --git a/src/runtime_test.cc b/src/runtime_test.cc
index 460fe44..e147749 100644
--- a/src/runtime_test.cc
+++ b/src/runtime_test.cc
@@ -56,8 +56,8 @@
   UniquePtr<Runtime::ParsedOptions> parsed(Runtime::ParsedOptions::Create(options, false));
   ASSERT_TRUE(parsed.get() != NULL);
 
-  EXPECT_EQ(lib_core, parsed->boot_class_path_);
-  EXPECT_EQ(lib_core, parsed->class_path_);
+  EXPECT_EQ(lib_core, parsed->boot_class_path_string_);
+  EXPECT_EQ(lib_core, parsed->class_path_string_);
   EXPECT_EQ(std::string("boot_image"), parsed->image_);
   EXPECT_EQ(true, parsed->check_jni_);
   EXPECT_EQ(2048U, parsed->heap_initial_size_);
diff --git a/src/zip_archive_test.cc b/src/zip_archive_test.cc
index bd0bc6d..7409ec4 100644
--- a/src/zip_archive_test.cc
+++ b/src/zip_archive_test.cc
@@ -36,14 +36,14 @@
 
   ScratchFile tmp;
   ASSERT_NE(-1, tmp.GetFd());
-  UniquePtr<File> file(OS::FileFromFd(tmp.GetFilename(), tmp.GetFd()));
+  UniquePtr<File> file(OS::FileFromFd(tmp.GetFilename().c_str(), tmp.GetFd()));
   ASSERT_TRUE(file.get() != NULL);
   bool success = zip_entry->ExtractToFile(*file);
   ASSERT_TRUE(success);
   close(tmp.GetFd());
 
   uint32_t computed_crc = crc32(0L, Z_NULL, 0);
-  int fd = open(tmp.GetFilename(), O_RDONLY);
+  int fd = open(tmp.GetFilename().c_str(), O_RDONLY);
   ASSERT_NE(-1, fd);
   const size_t kBufSize = 32768;
   uint8_t buf[kBufSize];
diff --git a/test/003-omnibus-opcodes/build b/test/003-omnibus-opcodes/build
index 1123582..bec2e74 100644
--- a/test/003-omnibus-opcodes/build
+++ b/test/003-omnibus-opcodes/build
@@ -24,4 +24,4 @@
 
 dx -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
 zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar classes.dex
-dex2oat --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat
+dex2oat --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --dex-location=/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat
diff --git a/test/022-interface/build b/test/022-interface/build
index a48bf20..4aec359 100644
--- a/test/022-interface/build
+++ b/test/022-interface/build
@@ -21,4 +21,4 @@
 # issue when interfaces override methods in Object
 dx --debug --dex --dump-to=classes.lst --output=classes.dex classes
 zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar classes.dex
-dex2oat --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat
+dex2oat --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --dex-location=/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat
diff --git a/test/023-many-interfaces/build b/test/023-many-interfaces/build
index 64c4cc2..4c73685 100644
--- a/test/023-many-interfaces/build
+++ b/test/023-many-interfaces/build
@@ -26,4 +26,4 @@
 
 dx --debug --dex --dump-to=classes.lst --output=classes.dex classes
 zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar classes.dex
-dex2oat --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat
+dex2oat --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --dex-location=/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat
diff --git a/test/056-const-string-jumbo/build b/test/056-const-string-jumbo/build
index 5b6c075..9043e6a 100644
--- a/test/056-const-string-jumbo/build
+++ b/test/056-const-string-jumbo/build
@@ -44,4 +44,4 @@
 
 dx -JXmx500m --debug --dex --no-optimize --positions=none --no-locals --dump-to=classes.lst --output=classes.dex classes
 zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar classes.dex
-dex2oat --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat
+dex2oat --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --dex-location=/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat
diff --git a/test/071-dexfile/info.txt b/test/071-dexfile/info.txt
index 54d9ed0..7328d71 100644
--- a/test/071-dexfile/info.txt
+++ b/test/071-dexfile/info.txt
@@ -1,4 +1,4 @@
 Exercise some Dalvik-specific DEX file features.  This is not expected to
 work on other VMs.
 
-NOTE: the test requires that /sdcard exists and is writable.
+NOTE: the test requires that /data/art-test/ exists and is writable and not mounted noexec.
diff --git a/test/085-old-style-inner-class/build b/test/085-old-style-inner-class/build
index 5ade65d..1162d1d 100644
--- a/test/085-old-style-inner-class/build
+++ b/test/085-old-style-inner-class/build
@@ -26,4 +26,4 @@
 dx --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes 2>/dev/null
 
 zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar classes.dex
-dex2oat --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat 2>/dev/null
+dex2oat --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --dex-location=/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat 2>/dev/null
diff --git a/test/etc/default-build b/test/etc/default-build
index b4c1a23..1d11c9f 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -26,7 +26,7 @@
 
 dx -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
 zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar classes.dex
-dex2oatd --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat
+dex2oatd --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar --dex-location=/data/art-test/$TEST_NAME.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar.oat
 
 if [ -r src-ex ]; then
     mkdir classes-ex
@@ -37,7 +37,7 @@
     mv classes.dex classes-1.dex
     mv classes-ex.dex classes.dex
     zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME-ex.jar classes.dex
-    dex2oatd --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME-ex.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME-ex.jar.oat
+    dex2oatd --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME-ex.jar --dex-location=/data/art-test/$TEST_NAME-ex.jar --oat-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME-ex.jar.oat
     mv classes.dex classes-ex.dex
     mv classes-1.dex classes.dex
 fi