Simplify command line arguments

Change-Id: I9d6902b0c447fd8fbe5600fd36139791b2ceefb7
diff --git a/Android.mk b/Android.mk
index bd37967..35825e1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -113,7 +113,7 @@
 	@echo test-art-target-run-test PASSED
 
 .PHONY: test-art-target-run-test-002
-test-art-target-run-test-002:
+test-art-target-run-test-002: test-art-target-sync
 	art/test/run-test 002
 	@echo test-art-target-run-test-002 PASSED
 
@@ -134,7 +134,7 @@
 test-art-target-oat-process-am: $(TARGET_OUT_JAVA_LIBRARIES)/am.oat test-art-target-sync
 	adb remount
 	adb sync
-	adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Xbootimage:/system/framework/boot.art -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am start http://android.com && touch /sdcard/test-art-target-process-am"
+	adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Ximage:/system/framework/boot.art -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am start http://android.com && touch /sdcard/test-art-target-process-am"
 	$(hide) (adb pull /sdcard/test-art-target-process-am /tmp/ && echo test-art-target-process-am PASSED) || echo test-art-target-process-am FAILED
 	$(hide) rm /tmp/test-art-target-process-am
 
@@ -158,7 +158,7 @@
 	  sleep 30; \
 	fi
 	adb shell kill `adb shell ps | fgrep com.android.calculator2 | sed -e 's/[^ ]* *\([0-9]*\).*/\1/'`
-	adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Xbootimage:/system/framework/boot.art -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am start -a android.intent.action.MAIN -n com.android.calculator2/.Calculator && touch /sdcard/test-art-target-process-Calculator"
+	adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Ximage:/system/framework/boot.art -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am start -a android.intent.action.MAIN -n com.android.calculator2/.Calculator && touch /sdcard/test-art-target-process-Calculator"
 	$(hide) (adb pull /sdcard/test-art-target-process-Calculator /tmp/ && echo test-art-target-process-Calculator PASSED) || echo test-art-target-process-Calculator FAILED
 	$(hide) rm /tmp/test-art-target-process-Calculator
 
@@ -170,17 +170,17 @@
 
 .PHONY: dump-oat-core
 dump-oat-core: $(TARGET_CORE_OAT) $(OATDUMP)
-	$(OATDUMP) $(addprefix --dex-file=,$(TARGET_CORE_DEX)) --oat=$(TARGET_CORE_OAT) --image=$(TARGET_CORE_IMG) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/core.oatdump.txt
+	$(OATDUMP) --image=$(TARGET_CORE_IMG) --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) $(addprefix --dex-file=,$(TARGET_BOOT_DEX)) --oat=$(TARGET_BOOT_OAT) --image=$(TARGET_BOOT_IMG) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/boot.oatdump.txt
+	$(OATDUMP) --image=$(TARGET_BOOT_IMG) --host-prefix=$(PRODUCT_OUT) --output=/tmp/boot.oatdump.txt
 	@echo Output in /tmp/boot.oatdump.txt
 
 .PHONY: dump-oat-Calculator
 dump-oat-Calculator: $(TARGET_OUT_APPS)/Calculator.oat $(TARGET_BOOT_OAT) $(OATDUMP)
-	$(OATDUMP) --dex-file=$(TARGET_OUT_APPS)/Calculator.apk --oat=$< --image=$(patsubst %.oat,%.art,$<) $(addprefix --boot-dex-file=,$(TARGET_BOOT_DEX)) --boot-oat=$(TARGET_BOOT_OAT) --boot-image=$(TARGET_BOOT_IMG) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/Calculator.oatdump.txt
+	$(OATDUMP) --image=$(patsubst %.oat,%.art,$<) --boot-image=$(TARGET_BOOT_IMG) --host-prefix=$(PRODUCT_OUT) --output=/tmp/Calculator.oatdump.txt
 	@echo Output in /tmp/Calculator.oatdump.txt
 
 
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index 52d5621..4839667 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -50,7 +50,7 @@
 # TODO: change DEX2OATD to order-only prerequisite when output is stable
 $(TARGET_CORE_OAT): $(TARGET_CORE_DEX) $(DEX2OAT)
 	@echo "target dex2oat: $@ ($<)"
-	$(hide) $(DEX2OAT) -Xms32m -Xmx32m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_CORE_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --strip-prefix=$(PRODUCT_OUT)
+	$(hide) $(DEX2OAT) -Xms32m -Xmx32m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_CORE_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
 
 ########################################################################
 # The full system boot classpath
@@ -62,4 +62,4 @@
 # TODO: change DEX2OATD to order-only prerequisite when output is stable
 $(TARGET_BOOT_OAT): $(TARGET_BOOT_DEX) $(DEX2OAT)
 	@echo "target dex2oat: $@ ($<)"
-	$(hide) $(DEX2OAT) -Xms256m -Xmx256m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_BOOT_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --strip-prefix=$(PRODUCT_OUT)
+	$(hide) $(DEX2OAT) -Xms256m -Xmx256m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_BOOT_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk
index ce615b2..b3dee96 100644
--- a/build/Android.oattest.mk
+++ b/build/Android.oattest.mk
@@ -40,7 +40,7 @@
 # TODO: change DEX2OATD (and perhaps $(2) boot oat) to order-only prerequisite when output is stable
 $(patsubst %.apk,%.oat,$(patsubst %.jar,%.oat,$(1))): $(1) $(2) $(DEX2OAT)
 	@echo "target dex2oat: $$@ ($$<)"
-	$(hide) $(DEX2OAT) -Xms16m -Xmx16m $(addprefix --boot-dex-file=,$(3)) --boot-oat=$(2) --boot-image=$(patsubst %.oat,%.art,$(2)) $(addprefix --dex-file=,$$<) --oat=$$@ --image=$$(patsubst %.oat,%.art,$$@) --strip-prefix=$(PRODUCT_OUT)
+	$(hide) $(DEX2OAT) -Xms16m -Xmx16m --boot-image=$(patsubst %.oat,%.art,$(2)) $(addprefix --dex-file=,$$<) --oat=$$@ --image=$$(patsubst %.oat,%.art,$$@) --host-prefix=$(PRODUCT_OUT)
 endef
 
 ########################################################################
@@ -64,7 +64,7 @@
 test-art-target-oat-$(1): test-art-target-sync
 	adb shell touch /sdcard/test-art-target-oat-$(1)
 	adb shell rm /sdcard/test-art-target-oat-$(1)
-	adb shell sh -c "oatexecd -Xbootclasspath:/system/framework/core.jar -Xbootoat:/system/framework/core.oat -Xbootimage:/system/framework/core.art -classpath /system/framework/art-test-dex-$(1).jar -Xoat:/system/framework/art-test-dex-$(1).oat -Ximage:/system/framework/art-test-dex-$(1).art $(1) $(2) && touch /sdcard/test-art-target-oat-$(1)"
+	adb shell sh -c "oatexecd -Ximage:/system/framework/core.art -classpath /system/framework/art-test-dex-$(1).jar -Ximage:/system/framework/art-test-dex-$(1).art $(1) $(2) && touch /sdcard/test-art-target-oat-$(1)"
 	$(hide) (adb pull /sdcard/test-art-target-oat-$(1) /tmp/ && echo test-art-target-oat-$(1) PASSED) || (echo test-art-target-oat-$(1) FAILED && exit 1)
 	$(hide) rm /tmp/test-art-target-oat-$(1)
 
diff --git a/oat_process/app_main.cpp b/oat_process/app_main.cpp
index 9ccdf16..c5ec8e9 100644
--- a/oat_process/app_main.cpp
+++ b/oat_process/app_main.cpp
@@ -212,9 +212,9 @@
     // TODO: remove Calculator special case
     int oatArgc = argc + 2;
     const char* oatArgv[oatArgc];
-    if (strcmp(argv[0], "-Xbootimage:/system/framework/boot.oat") != 0) {
+    if (strcmp(argv[0], "-Ximage:/system/framework/boot.oat") != 0) {
         LOG(INFO) << "Adding oat arguments";
-        oatArgv[0] = "-Xbootimage:/system/framework/boot.oat";
+        oatArgv[0] = "-Ximage:/system/framework/boot.oat";
         oatArgv[1] = "-Ximage:/system/app/Calculator.oat";
         setenv("CLASSPATH", "/system/app/Calculator.apk", 1);
         memcpy(oatArgv + (oatArgc - argc), argv, argc * sizeof(*argv));
diff --git a/src/class_linker.cc b/src/class_linker.cc
index b4e332d..d3a6ed0 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -16,10 +16,12 @@
 #include "intern_table.h"
 #include "logging.h"
 #include "monitor.h"
+#include "oat_file.h"
 #include "object.h"
 #include "runtime.h"
 #include "ScopedLocalRef.h"
 #include "space.h"
+#include "stl_util.h"
 #include "thread.h"
 #include "UniquePtr.h"
 #include "utils.h"
@@ -177,17 +179,17 @@
   DISALLOW_COPY_AND_ASSIGN(ObjectLock);
 };
 
-ClassLinker* ClassLinker::Create(const std::vector<const DexFile*>& boot_class_path,
-                                 const std::vector<const DexFile*>& class_path,
-                                 InternTable* intern_table, bool image) {
+ClassLinker* ClassLinker::Create(const std::string& boot_class_path,
+                                 InternTable* intern_table) {
   CHECK_NE(boot_class_path.size(), 0U);
   UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
-  if (image) {
-    class_linker->InitFromImage(boot_class_path, class_path);
-  } else {
-    class_linker->Init(boot_class_path, class_path);
-  }
-  // TODO: check for failure during initialization
+  class_linker->Init(boot_class_path);
+  return class_linker.release();
+}
+
+ClassLinker* ClassLinker::Create(InternTable* intern_table) {
+  UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
+  class_linker->InitFromImage();
   return class_linker.release();
 }
 
@@ -201,8 +203,19 @@
   CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax));
 }
 
-void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path,
-                       const std::vector<const DexFile*>& class_path) {
+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) {
+      class_path_vector.push_back(dex_file);
+    }
+  }
+}
+
+void ClassLinker::Init(const std::string& boot_class_path) {
   const Runtime* runtime = Runtime::Current();
   if (runtime->IsVerboseStartup()) {
     LOG(INFO) << "ClassLinker::InitFrom entering";
@@ -290,16 +303,13 @@
 
   // setup boot_class_path_ and register class_path now that we can
   // use AllocObjectArray to create DexCache instances
-  for (size_t i = 0; i != boot_class_path.size(); ++i) {
-    const DexFile* dex_file = boot_class_path[i];
+  std::vector<const DexFile*> boot_class_path_vector;
+  CreateClassPath(boot_class_path, boot_class_path_vector);
+  for (size_t i = 0; i != boot_class_path_vector.size(); ++i) {
+    const DexFile* dex_file = boot_class_path_vector[i];
     CHECK(dex_file != NULL);
     AppendToBootClassPath(*dex_file);
   }
-  for (size_t i = 0; i != class_path.size(); ++i) {
-    const DexFile* dex_file = class_path[i];
-    CHECK(dex_file != NULL);
-    RegisterDexFile(*dex_file);
-  }
 
   // Constructor, Field, and Method are necessary so that FindClass can link members
   Class* java_lang_reflect_Constructor = AllocClass(java_lang_Class, sizeof(MethodClass));
@@ -523,6 +533,36 @@
   }
 }
 
+OatFile* ClassLinker::OpenOat(const Space* space) {
+  const Runtime* runtime = Runtime::Current();
+  if (runtime->IsVerboseStartup()) {
+    LOG(INFO) << "ClassLinker::OpenOat entering";
+  }
+  const ImageHeader& image_header = space->GetImageHeader();
+  String* oat_location = image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString();
+  std::string oat_filename;
+  oat_filename += runtime->GetHostPrefix();
+  oat_filename += oat_location->ToModifiedUtf8();
+  OatFile* oat_file = OatFile::Open(std::string(oat_filename), "", image_header.GetOatBaseAddr());
+  if (oat_file == NULL) {
+    LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image";
+    return NULL;
+  }
+  uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
+  uint32_t image_oat_checksum = image_header.GetOatChecksum();
+  if (oat_checksum != image_oat_checksum) {
+    LOG(ERROR) << "Failed to match oat filechecksum " << std::hex << oat_checksum
+               << " to expected oat checksum " << std::hex << oat_checksum
+               << " in image";
+    return NULL;
+  }
+  oat_files_.push_back(oat_file);
+  if (runtime->IsVerboseStartup()) {
+    LOG(INFO) << "ClassLinker::OpenOat exiting";
+  }
+  return oat_file;
+}
+
 struct ClassLinker::InitFromImageCallbackState {
   ClassLinker* class_linker;
 
@@ -530,19 +570,47 @@
 
   typedef std::tr1::unordered_map<std::string, ClassRoot> Table;
   Table descriptor_to_class_root;
-
-  typedef std::tr1::unordered_set<DexCache*, DexCacheHash> Set;
-  Set dex_caches;
 };
 
-void ClassLinker::InitFromImage(const std::vector<const DexFile*>& boot_class_path,
-                                const std::vector<const DexFile*>& class_path) {
+void ClassLinker::InitFromImage() {
   const Runtime* runtime = Runtime::Current();
   if (runtime->IsVerboseStartup()) {
     LOG(INFO) << "ClassLinker::InitFromImage entering";
   }
   CHECK(!init_done_);
 
+  const std::vector<Space*>& spaces = Heap::GetSpaces();
+  for (size_t i = 0; i < spaces.size(); i++) {
+    Space* space = spaces[i] ;
+    if (space->IsImageSpace()) {
+      OatFile* oat_file = OpenOat(space);
+      CHECK(oat_file != NULL) << "Failed to open oat file for image";
+      Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
+      ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>();
+
+      CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
+               static_cast<uint32_t>(dex_caches->GetLength()));
+      for (int i = 0; i < dex_caches->GetLength(); i++) {
+        DexCache* dex_cache = dex_caches->Get(i);
+        const std::string& dex_file_location = dex_cache->GetLocation()->ToModifiedUtf8();
+
+        std::string dex_filename;
+        dex_filename += runtime->GetHostPrefix();
+        dex_filename += dex_file_location;
+        const DexFile* dex_file = DexFile::Open(dex_filename, runtime->GetHostPrefix());
+        if (dex_file == NULL) {
+          LOG(FATAL) << "Failed to open dex file " << dex_filename
+                     << " referenced from oat file as " << dex_file_location;
+        }
+
+        const OatFile::OatDexFile& oat_dex_file = oat_file->GetOatDexFile(dex_file_location);
+        CHECK_EQ(dex_file->GetHeader().checksum_, oat_dex_file.GetDexFileChecksum());
+
+        RegisterDexFile(*dex_file, dex_cache);
+      }
+    }
+  }
+
   HeapBitmap* heap_bitmap = Heap::GetLiveBits();
   DCHECK(heap_bitmap != NULL);
 
@@ -568,36 +636,6 @@
   array_interfaces_ = GetClassRoot(kObjectArrayClass)->GetInterfaces();
   DCHECK(array_interfaces_ == GetClassRoot(kBooleanArrayClass)->GetInterfaces());
 
-  // build a map from location to DexCache to match up with DexFile::GetLocation
-  std::tr1::unordered_map<std::string, DexCache*> location_to_dex_cache;
-  typedef InitFromImageCallbackState::Set::const_iterator It;  // TODO: C++0x auto
-  for (It it = state.dex_caches.begin(), end = state.dex_caches.end(); it != end; ++it) {
-    DexCache* dex_cache = *it;
-    std::string location = dex_cache->GetLocation()->ToModifiedUtf8();
-    location_to_dex_cache[location] = dex_cache;
-  }
-  CHECK(boot_class_path.size() + class_path.size() == location_to_dex_cache.size())
-      << "(" << boot_class_path.size() << " + " << class_path.size()
-      << " != " << location_to_dex_cache.size() << ")";
-
-  // reinit boot_class_path with DexFile arguments and found DexCaches
-  for (size_t i = 0; i != boot_class_path.size(); ++i) {
-    const DexFile* dex_file = boot_class_path[i];
-    CHECK(dex_file != NULL);
-    DexCache* dex_cache = location_to_dex_cache[dex_file->GetLocation()];
-    CHECK(dex_cache != NULL) << dex_file->GetLocation();
-    AppendToBootClassPath(*dex_file, dex_cache);
-  }
-
-  // register class_path with DexFile arguments and found DexCaches
-  for (size_t i = 0; i != class_path.size(); ++i) {
-    const DexFile* dex_file = class_path[i];
-    CHECK(dex_file != NULL);
-    DexCache* dex_cache = location_to_dex_cache[dex_file->GetLocation()];
-    CHECK(dex_cache != NULL) << dex_file->GetLocation();
-    RegisterDexFile(*dex_file, dex_cache);
-  }
-
   String::SetClass(GetClassRoot(kJavaLangString));
   Field::SetClass(GetClassRoot(kJavaLangReflectField));
   Method::SetClasses(GetClassRoot(kJavaLangReflectConstructor), GetClassRoot(kJavaLangReflectMethod));
@@ -644,14 +682,6 @@
   // restore class to ClassLinker::classes_ table
   state->class_linker->InsertClass(descriptor, klass);
 
-  // note DexCache to match with DexFile later
-  DexCache* dex_cache = klass->GetDexCache();
-  if (dex_cache != NULL) {
-    state->dex_caches.insert(dex_cache);
-  } else {
-    DCHECK(klass->IsArrayClass() || klass->IsPrimitive());
-  }
-
   // check if this is a root, if so, register it
   typedef InitFromImageCallbackState::Table::const_iterator It;  // TODO: C++0x auto
   It it = state->descriptor_to_class_root.find(descriptor);
@@ -696,6 +726,8 @@
   ShortArray::ResetArrayClass();
   PathClassLoader::ResetClass();
   StackTraceElement::ResetClass();
+  STLDeleteElements(&boot_class_path_);
+  STLDeleteElements(&oat_files_);
 }
 
 DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) {
diff --git a/src/class_linker.h b/src/class_linker.h
index 3c483a9..747a6e4 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -25,6 +25,7 @@
 #include "heap.h"
 #include "macros.h"
 #include "mutex.h"
+#include "oat_file.h"
 #include "object.h"
 #include "unordered_map.h"
 #include "unordered_set.h"
@@ -39,10 +40,11 @@
 
 class ClassLinker {
  public:
-  // Initializes the class linker using DexFiles and an optional an image.
-  static ClassLinker* Create(const std::vector<const DexFile*>& boot_class_path,
-                             const std::vector<const DexFile*>& class_path,
-                             InternTable* intern_table, bool image);
+  // Creates the class linker by boot strapping from dex files.
+  static ClassLinker* Create(const std::string& boot_class_path, InternTable* intern_table);
+
+  // Creates the class linker from one or more images.
+  static ClassLinker* Create(InternTable* intern_table);
 
   ~ClassLinker();
 
@@ -191,13 +193,12 @@
  private:
   ClassLinker(InternTable*);
 
-  // Initialize class linker from DexFile instances.
-  void Init(const std::vector<const DexFile*>& boot_class_path_,
-            const std::vector<const DexFile*>& class_path_);
+  // Initialize class linker by bootstraping from dex files
+  void Init(const std::string& boot_class_path);
 
-  // Initialize class linker from pre-initialized image.
-  void InitFromImage(const std::vector<const DexFile*>& boot_class_path_,
-                     const std::vector<const DexFile*>& class_path_);
+  // Initialize class linker from one or more images.
+  void InitFromImage();
+  OatFile* OpenOat(const Space* space);
   static void InitFromImageCallback(Object* obj, void* arg);
   struct InitFromImageCallbackState;
 
@@ -298,9 +299,16 @@
   void CreateReferenceOffsets(Class *klass, bool instance,
                               uint32_t reference_offsets);
 
+  // For use by ImageWriter to find DexCaches for its roots
+  const std::vector<DexCache*>& GetDexCaches() {
+    return dex_caches_;
+  }
+
   // lock to protect ClassLinker state
   mutable Mutex lock_;
 
+  std::vector<const OatFile*> oat_files_;
+
   std::vector<const DexFile*> boot_class_path_;
 
   std::vector<const DexFile*> dex_files_;
@@ -389,6 +397,7 @@
   friend class ObjectTest;
   FRIEND_TEST(ObjectTest, AllocObjectArray);
   FRIEND_TEST(ExceptionTest, FindExceptionHandler);
+  friend class ImageWriter;  // for GetDexCaches
   DISALLOW_COPY_AND_ASSIGN(ClassLinker);
 };
 
diff --git a/src/common_test.h b/src/common_test.h
index a7c5ea8..b321071 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -43,7 +43,7 @@
   file.reset();
 
   // read dex file
-  const DexFile* dex_file = DexFile::OpenFile(location, location, "");
+  const DexFile* dex_file = DexFile::Open(location, "");
   CHECK(dex_file != NULL);
   return dex_file;
 }
@@ -114,10 +114,12 @@
 
     java_lang_dex_file_.reset(GetLibCoreDex());
 
-    boot_class_path_.push_back(java_lang_dex_file_.get());
+    std::string boot_class_path;
+    boot_class_path += "-Xbootclasspath:";
+    boot_class_path += GetLibCoreDexFileName();
 
     Runtime::Options options;
-    options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
+    options.push_back(std::make_pair(boot_class_path.c_str(), reinterpret_cast<void*>(NULL)));
     options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL)));
     options.push_back(std::make_pair("-Xms64m", reinterpret_cast<void*>(NULL)));
     options.push_back(std::make_pair("-Xmx64m", reinterpret_cast<void*>(NULL)));
@@ -193,7 +195,7 @@
 
   const DexFile* GetLibCoreDex() {
     std::string libcore_dex_file_name = GetLibCoreDexFileName();
-    return DexFile::OpenZip(libcore_dex_file_name, "");
+    return DexFile::Open(libcore_dex_file_name, "");
   }
 
   uint32_t FindTypeIdxByDescriptor(const DexFile& dex_file, const StringPiece& descriptor) {
@@ -239,7 +241,7 @@
     filename += "/system/framework/art-test-dex-";
     filename += name;
     filename += ".jar";
-    const DexFile* dex_file = DexFile::OpenZip(filename, "");
+    const DexFile* dex_file = DexFile::Open(filename, "");
     CHECK(dex_file != NULL) << "Failed to open " << filename;
     return dex_file;
   }
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 78d3628..d34a681 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -42,25 +42,14 @@
           "  --boot-image=<file.art>: provide the image file for the boot class path.\n"
           "      Example: --boot-image=/system/framework/boot.art\n"
           "\n");
-  // TODO: remove this by inferring from --boot-image
-  fprintf(stderr,
-          "  --boot-oat=<file.oat>: provide the oat file for the boot class path.\n"
-          "      Example: --boot-oat=/system/framework/boot.oat\n"
-          "\n");
-  // TODO: remove this by inderring from --boot-image or --boot-oat
-  fprintf(stderr,
-          "  --boot-dex-file=<dex-file>: specifies a .dex file that is part of the boot\n"
-          "      image specified with --boot. \n"
-          "      Example: --boot-dex-file=/system/framework/core.jar\n"
-          "\n");
   fprintf(stderr,
           "  --method may be used to limit compilation to a subset of methods.\n"
           "      Example: --method=Ljava/lang/Object;<init>()V\n"
           "\n");
   fprintf(stderr,
-          "  --strip-prefix may be used to strip a path prefix from dex file names in the\n"
-          "      the generated image to match the target file system layout.\n"
-          "      Example: --strip-prefix=out/target/product/crespo\n"
+          "  --host-prefix may be used to translate host paths to target paths during\n"
+          "      cross compilation.\n"
+          "      Example: --host-prefix=out/target/product/crespo\n"
           "\n");
   fprintf(stderr,
           "  -Xms<n> may be used to specify an initial heap size for the runtime used to\n"
@@ -90,10 +79,8 @@
   std::string oat_filename;
   const char* image_filename = NULL;
   std::string boot_image_option;
-  std::string boot_oat_option;
-  std::vector<const char*> boot_dex_filenames;
   uintptr_t image_base = 0;
-  std::string strip_location_prefix;
+  std::string host_prefix;
   const char* Xms = NULL;
   const char* Xmx = NULL;
 
@@ -118,17 +105,10 @@
     } else if (option.starts_with("--boot-image=")) {
       const char* boot_image_filename = option.substr(strlen("--boot-image=")).data();
       boot_image_option.clear();
-      boot_image_option += "-Xbootimage:";
+      boot_image_option += "-Ximage:";
       boot_image_option += boot_image_filename;
-    } else if (option.starts_with("--boot-oat=")) {
-      const char* boot_oat_filename = option.substr(strlen("--boot-oat=")).data();
-      boot_oat_option.clear();
-      boot_oat_option += "-Xbootoat:";
-      boot_oat_option += boot_oat_filename;
-    } else if (option.starts_with("--boot-dex-file=")) {
-      boot_dex_filenames.push_back(option.substr(strlen("--boot-dex-file=")).data());
-    } else if (option.starts_with("--strip-prefix=")) {
-      strip_location_prefix = option.substr(strlen("--strip-prefix=")).data();
+    } else if (option.starts_with("--host-prefix=")) {
+      host_prefix = option.substr(strlen("--host-prefix=")).data();
     } else if (option.starts_with("-Xms")) {
       Xms = option.data();
     } else if (option.starts_with("-Xmx")) {
@@ -154,36 +134,25 @@
    return EXIT_FAILURE;
   }
 
-  if (boot_image_option.empty() != boot_oat_option.empty()) {
-   fprintf(stderr, "--boot-image and --boat-oat must be specified together or not at all\n");
-   return EXIT_FAILURE;
-  }
-
   if (boot_image_option.empty()) {
     if (image_base == 0) {
       fprintf(stderr, "non-zero --base not specified\n");
       return EXIT_FAILURE;
     }
-  } else {
-    if (boot_dex_filenames.empty()) {
-      fprintf(stderr, "no --boot-dex-file values specified with --boot-image\n");
-      return EXIT_FAILURE;
-    }
   }
 
-  std::vector<const DexFile*> dex_files;
-  DexFile::OpenDexFiles(dex_filenames, dex_files, strip_location_prefix);
-
-  std::vector<const DexFile*> boot_dex_files;
-  DexFile::OpenDexFiles(boot_dex_filenames, boot_dex_files, strip_location_prefix);
-
   Runtime::Options options;
+ std::string boot_class_path_string;
   if (boot_image_option.empty()) {
-    options.push_back(std::make_pair("bootclasspath", &dex_files));
+    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)));
   } else {
-    options.push_back(std::make_pair("bootclasspath", &boot_dex_files));
     options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
-    options.push_back(std::make_pair(boot_oat_option.c_str(), reinterpret_cast<void*>(NULL)));
   }
   if (Xms != NULL) {
     options.push_back(std::make_pair(Xms, reinterpret_cast<void*>(NULL)));
@@ -191,6 +160,9 @@
   if (Xmx != NULL) {
     options.push_back(std::make_pair(Xmx, reinterpret_cast<void*>(NULL)));
   }
+  if (!host_prefix.empty()) {
+    options.push_back(std::make_pair("host-prefix", host_prefix.c_str()));
+  }
   UniquePtr<Runtime> runtime(Runtime::Create(options, false));
   if (runtime.get() == NULL) {
     fprintf(stderr, "could not create runtime\n");
@@ -199,10 +171,12 @@
   ClassLinker* class_linker = runtime->GetClassLinker();
 
   // If we have an existing boot image, position new space after its oat file
-  if (!boot_image_option.empty()) {
-    Space* boot_space = Heap::GetBootSpace();
-    CHECK(boot_space != NULL);
-    byte* oat_limit_addr = boot_space->GetImageHeader().GetOatLimitAddr();
+  if (Heap::GetSpaces().size() > 1) {
+    Space* last_image_space = Heap::GetSpaces()[Heap::GetSpaces().size()-2];
+    CHECK(last_image_space != NULL);
+    CHECK(last_image_space->IsImageSpace());
+    CHECK(!Heap::GetSpaces()[Heap::GetSpaces().size()-1]->IsImageSpace());
+    byte* oat_limit_addr = last_image_space->GetImageHeader().GetOatLimitAddr();
     image_base = RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr), kPageSize);
   }
 
@@ -211,6 +185,8 @@
   if (boot_image_option.empty()) {
     class_loader = NULL;
   } else {
+    std::vector<const DexFile*> dex_files;
+    DexFile::OpenDexFiles(dex_filenames, dex_files, host_prefix);
     for (size_t i = 0; i < dex_files.size(); i++) {
       class_linker->RegisterDexFile(*dex_files[i]);
     }
@@ -279,7 +255,7 @@
   }
 
   ImageWriter image_writer;
-  if (!image_writer.Write(image_filename, image_base, oat_filename, strip_location_prefix)) {
+  if (!image_writer.Write(image_filename, image_base, oat_filename, host_prefix)) {
     fprintf(stderr, "Failed to create image file %s\n", image_filename);
     return EXIT_FAILURE;
   }
diff --git a/src/dex_file.cc b/src/dex_file.cc
index b4cf837..474d742 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -59,8 +59,7 @@
 const DexFile* DexFile::Open(const std::string& filename,
                              const std::string& strip_location_prefix) {
   if (filename.size() < 4) {
-    LOG(WARNING) << "Ignoring short classpath entry '" << filename << "'";
-    return NULL;
+    LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'";
   }
   std::string suffix(filename.substr(filename.size() - 4));
   if (suffix == ".zip" || suffix == ".jar" || suffix == ".apk") {
@@ -106,7 +105,7 @@
   }
   close(fd);
   byte* dex_file = map->GetAddress();
-  return Open(dex_file, length, location.ToString(), map.release());
+  return OpenMemory(dex_file, length, location.ToString(), map.release());
 }
 
 static const char* kClassesDex = "classes.dex";
@@ -349,8 +348,8 @@
   // NOTREACHED
 }
 
-const DexFile* DexFile::Open(const byte* dex_bytes, size_t length,
-                             const std::string& location, MemMap* mem_map) {
+const DexFile* DexFile::OpenMemory(const byte* dex_bytes, size_t length,
+                                   const std::string& location, MemMap* mem_map) {
   UniquePtr<DexFile> dex_file(new DexFile(dex_bytes, length, location, mem_map));
   if (!dex_file->Init()) {
     return NULL;
diff --git a/src/dex_file.h b/src/dex_file.h
index cb979ae..45cd33e 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -324,19 +324,9 @@
                            std::vector<const DexFile*>& dex_files,
                            const std::string& strip_location_prefix);
 
-  // Opens .dex file, guessing the format based on file extension
+  // 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);
-
-  // Opens a .dex file from the file system.
-  static const DexFile* OpenFile(const std::string& filename,
-                                 const std::string& original_location,
-                                 const std::string& strip_location_prefix);
-
-  // Opens a .jar, .zip, or .apk file from the file system.
-  static const DexFile* OpenZip(const std::string& filename,
-                                const std::string& strip_location_prefix);
-
   // Closes a .dex file.
   virtual ~DexFile();
 
@@ -838,11 +828,21 @@
   void ChangePermissions(int prot) const;
 
  private:
+
+  // Opens a .dex file
+  static const DexFile* OpenFile(const std::string& filename,
+                                 const std::string& original_location,
+                                 const std::string& strip_location_prefix);
+
+  // 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);
+
   // Opens a .dex file at the given address.
-  static const DexFile* Open(const byte* dex_file,
-                             size_t length,
-                             const std::string& location,
-                             MemMap* mem_map);
+  static const DexFile* OpenMemory(const byte* dex_file,
+                                   size_t length,
+                                   const std::string& location,
+                                   MemMap* mem_map);
 
   DexFile(const byte* addr, size_t length, const std::string& location, MemMap* mem_map)
       : base_(addr),
diff --git a/src/heap.cc b/src/heap.cc
index 2051051..92ebbd0 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2,6 +2,7 @@
 
 #include "heap.h"
 
+#include <limits>
 #include <vector>
 
 #include "UniquePtr.h"
@@ -16,8 +17,6 @@
 
 std::vector<Space*> Heap::spaces_;
 
-Space* Heap::boot_space_ = NULL;
-
 Space* Heap::alloc_space_ = NULL;
 
 size_t Heap::maximum_size_ = 0;
@@ -56,29 +55,19 @@
 };
 
 void Heap::Init(size_t initial_size, size_t maximum_size,
-                const char* boot_image_file_name,
-                std::vector<const char*>& image_file_names) {
+                const std::vector<std::string>& image_file_names) {
   const Runtime* runtime = Runtime::Current();
   if (runtime->IsVerboseStartup()) {
     LOG(INFO) << "Heap::Init entering";
   }
 
-  Space* boot_space;
-  byte* requested_base;
-  if (boot_image_file_name == NULL) {
-    boot_space = NULL;
-    requested_base = NULL;
-  } else {
-    boot_space = Space::CreateFromImage(boot_image_file_name);
-    if (boot_space == NULL) {
-      LOG(FATAL) << "Failed to create space from " << boot_image_file_name;
-    }
-    spaces_.push_back(boot_space);
-    byte* oat_limit_addr = boot_space->GetImageHeader().GetOatLimitAddr();
-    requested_base = reinterpret_cast<byte*>(RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr),
-                                                     kPageSize));
-  }
+  // bounds of all spaces for allocating live and mark bitmaps
+  // there will be at least one space (the alloc space),
+  // so set to base to max and limit to min to start
+  byte* base = reinterpret_cast<byte*>(std::numeric_limits<uintptr_t>::max());
+  byte* limit = reinterpret_cast<byte*>(std::numeric_limits<uintptr_t>::min());
 
+  byte* requested_base = NULL;
   std::vector<Space*> image_spaces;
   for (size_t i = 0; i < image_file_names.size(); i++) {
     Space* space = Space::CreateFromImage(image_file_names[i]);
@@ -88,20 +77,20 @@
     image_spaces.push_back(space);
     spaces_.push_back(space);
     byte* oat_limit_addr = space->GetImageHeader().GetOatLimitAddr();
-    requested_base = reinterpret_cast<byte*>(RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr),
-                                                     kPageSize));
+    if (oat_limit_addr > requested_base) {
+      requested_base = reinterpret_cast<byte*>(RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr),
+                                                       kPageSize));
+    }
+    base = std::min(base, space->GetBase());
+    limit = std::max(limit, space->GetLimit());
   }
 
   Space* space = Space::Create(initial_size, maximum_size, requested_base);
   if (space == NULL) {
     LOG(FATAL) << "Failed to create alloc space";
   }
-
-  if (boot_space == NULL) {
-    boot_space = space;
-  }
-  byte* base = std::min(boot_space->GetBase(), space->GetBase());
-  byte* limit = std::max(boot_space->GetLimit(), space->GetLimit());
+  base = std::min(base, space->GetBase());
+  limit = std::max(limit, space->GetLimit());
   DCHECK_LT(base, limit);
   size_t num_bytes = limit - base;
 
@@ -128,11 +117,7 @@
 
   // TODO: allocate the card table
 
-  // Make objects in boot_space live (after live_bitmap_ is set)
-  if (boot_image_file_name != NULL) {
-    boot_space_ = boot_space;
-    RecordImageAllocations(boot_space);
-  }
+  // Make image objects live (after live_bitmap_ is set)
   for (size_t i = 0; i < image_spaces.size(); i++) {
     RecordImageAllocations(image_spaces[i]);
   }
diff --git a/src/heap.h b/src/heap.h
index b669a86..76e33b5 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -41,12 +41,11 @@
 
   typedef void (RootVisitor)(const Object* root, void* arg);
 
-  // Create a heap with the requested sizes. The optional boot image may
-  // be NULL, otherwise it is an image filename created by ImageWriter.
-  // image_file_names specifies application images to load.
+  // Create a heap with the requested sizes. The possible empty
+  // image_file_names names specify Spaces to load based on
+  // ImageWriter output.
   static void Init(size_t starting_size, size_t maximum_size,
-                   const char* boot_image_file_name,
-                   std::vector<const char*>& image_file_names);
+                   const std::vector<std::string>& image_file_names);
 
   static void Destroy();
 
@@ -105,10 +104,6 @@
     return spaces_;
   }
 
-  static Space* GetBootSpace() {
-    return boot_space_;
-  }
-
   static HeapBitmap* GetLiveBits() {
     return live_bitmap_;
   }
@@ -199,10 +194,6 @@
 
   static std::vector<Space*> spaces_;
 
-  // Space loaded from an image
-  // TODO: remove after intern_addr is removed
-  static Space* boot_space_;
-
   // default Space for allocations
   static Space* alloc_space_;
 
diff --git a/src/image.h b/src/image.h
index 3d2f5f4..4a2efc5 100644
--- a/src/image.h
+++ b/src/image.h
@@ -70,6 +70,7 @@
     kAbstractMethodErrorStubArray,
     kCalleeSaveMethod,
     kOatLocation,
+    kDexCaches,
     kImageRootsMax,
   };
 
diff --git a/src/image_test.cc b/src/image_test.cc
index 2fd5c34..903457f 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -23,8 +23,8 @@
 
   ImageWriter writer;
   ScratchFile tmp_image;
-  const uintptr_t image_base = 0x50000000;
-  bool success_image = writer.Write(tmp_image.GetFilename(), image_base,
+  const uintptr_t requested_image_base = 0x60000000;
+  bool success_image = writer.Write(tmp_image.GetFilename(), requested_image_base,
                                     std::string(tmp_oat.GetFilename()), "");
   ASSERT_TRUE(success_image);
 
@@ -51,17 +51,10 @@
   UniquePtr<const DexFile> dex(GetLibCoreDex());
   ASSERT_TRUE(dex.get() != NULL);
 
-  std::vector<const DexFile*> boot_class_path;
-  boot_class_path.push_back(dex.get());
-
   Runtime::Options options;
-  options.push_back(std::make_pair("bootclasspath", &boot_class_path));
-  std::string boot_oat("-Xbootoat:");
-  boot_oat.append(tmp_oat.GetFilename());
-  options.push_back(std::make_pair(boot_oat.c_str(), reinterpret_cast<void*>(NULL)));
-  std::string boot_image("-Xbootimage:");
-  boot_image.append(tmp_image.GetFilename());
-  options.push_back(std::make_pair(boot_image.c_str(), reinterpret_cast<void*>(NULL)));
+  std::string image("-Ximage:");
+  image.append(tmp_image.GetFilename());
+  options.push_back(std::make_pair(image.c_str(), reinterpret_cast<void*>(NULL)));
 
   runtime_.reset(Runtime::Create(options, false));
   ASSERT_TRUE(runtime_.get() != NULL);
@@ -70,23 +63,20 @@
   ASSERT_TRUE(runtime_->GetJniStubArray() != NULL);
 
   ASSERT_EQ(2U, Heap::GetSpaces().size());
-  Space* boot_space = Heap::GetBootSpace();
-  ASSERT_TRUE(boot_space != NULL);
+  ASSERT_TRUE(Heap::GetSpaces()[0]->IsImageSpace());
+  ASSERT_FALSE(Heap::GetSpaces()[1]->IsImageSpace());
 
-  // enable to display maps to debug boot_base and boot_limit checking problems below
-  if (false) {
-    SignalCatcher::HandleSigQuit();
-  }
-
-  byte* boot_base = boot_space->GetBase();
-  byte* boot_limit = boot_space->GetLimit();
+  Space* image_space = Heap::GetSpaces()[0];
+  byte* image_base = image_space->GetBase();
+  byte* image_limit = image_space->GetLimit();
+  CHECK_EQ(requested_image_base, reinterpret_cast<uintptr_t>(image_base));
   for (size_t i = 0; i < dex->NumClassDefs(); i++) {
     const DexFile::ClassDef& class_def = dex->GetClassDef(i);
     const char* descriptor = dex->GetClassDescriptor(class_def);
     Class* klass = class_linker_->FindSystemClass(descriptor);
     EXPECT_TRUE(klass != NULL) << descriptor;
-    EXPECT_LT(boot_base, reinterpret_cast<byte*>(klass)) << descriptor;
-    EXPECT_LT(reinterpret_cast<byte*>(klass), boot_limit) << descriptor;
+    EXPECT_LT(image_base, reinterpret_cast<byte*>(klass)) << descriptor;
+    EXPECT_LT(reinterpret_cast<byte*>(klass), image_limit) << descriptor;
     EXPECT_EQ(*klass->GetRawLockWordAddress(), 0);  // address should have been removed from monitor
   }
 }
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 37eac2e..2b2ada4 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -32,6 +32,7 @@
   // currently just write the last space, assuming it is the space that was being used for allocation
   CHECK_GE(spaces.size(), 1U);
   source_space_ = spaces[spaces.size()-1];
+  CHECK(!source_space_->IsImageSpace());
 
   oat_file_.reset(OatFile::Open(oat_filename, strip_location_prefix, NULL));
   if (oat_file_.get() == NULL) {
@@ -114,10 +115,26 @@
 }
 
 ObjectArray<Object>* ImageWriter::CreateImageRoots() const {
-  // build a Object[] of the roots needed to restore the runtime
   Runtime* runtime = Runtime::Current();
   ClassLinker* class_linker = runtime->GetClassLinker();
   Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;");
+
+  // build an Object[] of all the DexCaches used in the source_space_
+  const std::vector<DexCache*>& all_dex_caches = class_linker->GetDexCaches();
+  std::vector<DexCache*> source_space_dex_caches;
+  for (size_t i = 0; i < all_dex_caches.size(); i++) {
+    DexCache* dex_cache = all_dex_caches[i];
+    if (InSourceSpace(dex_cache)) {
+      source_space_dex_caches.push_back(dex_cache);
+    }
+  }
+  ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(object_array_class,
+                                                               source_space_dex_caches.size());
+  for (size_t i = 0; i < source_space_dex_caches.size(); i++) {
+      dex_caches->Set(i, source_space_dex_caches[i]);
+  }
+
+  // build an Object[] of the roots needed to restore the runtime
   ObjectArray<Object>* image_roots = ObjectArray<Object>::Alloc(object_array_class,
                                                                 ImageHeader::kImageRootsMax);
   image_roots->Set(ImageHeader::kJniStubArray,
@@ -128,6 +145,8 @@
                    runtime->GetCalleeSaveMethod());
   image_roots->Set(ImageHeader::kOatLocation,
                    String::AllocFromModifiedUtf8(oat_file_->GetLocation().c_str()));
+  image_roots->Set(ImageHeader::kDexCaches,
+                   dex_caches);
   for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
     CHECK(image_roots->Get(i) != NULL);
   }
diff --git a/src/image_writer.h b/src/image_writer.h
index 8c4b308..fda33fe 100644
--- a/src/image_writer.h
+++ b/src/image_writer.h
@@ -62,12 +62,12 @@
     object->monitor_ = 0;
   }
 
-  bool InSourceSpace(const Object* object) {
+  bool InSourceSpace(const Object* object) const {
     DCHECK(source_space_ != NULL);
     const byte* o = reinterpret_cast<const byte*>(object);
     return (o >= source_space_->GetBase() && o < source_space_->GetLimit());
   }
-  Object* GetImageAddress(const Object* object) {
+  Object* GetImageAddress(const Object* object) const {
     if (object == NULL) {
       return NULL;
     }
@@ -77,7 +77,7 @@
     }
     return reinterpret_cast<Object*>(image_base_ + GetImageOffset(object));
   }
-  Object* GetLocalAddress(const Object* object) {
+  Object* GetLocalAddress(const Object* object) const {
     size_t offset = GetImageOffset(object);
     byte* dst = image_->GetAddress() + offset;
     return reinterpret_cast<Object*>(dst);
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 6266494..15221a6 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -123,10 +123,10 @@
   return mem_map_->GetLimit();
 }
 
-const OatFile::OatDexFile& OatFile::GetOatDexFile(const DexFile& dex_file) {
-  Table::const_iterator it = oat_dex_files_.find(dex_file.GetLocation());
+const OatFile::OatDexFile& OatFile::GetOatDexFile(const std::string& dex_file_location) {
+  Table::const_iterator it = oat_dex_files_.find(dex_file_location);
   if (it == oat_dex_files_.end()) {
-    LOG(FATAL) << "Failed to find OatDexFile for DexFile " << dex_file.GetLocation();
+    LOG(FATAL) << "Failed to find OatDexFile for DexFile " << dex_file_location;
   }
   return *it->second;
 }
diff --git a/src/oat_file.h b/src/oat_file.h
index 2528a6c..6027dda 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -51,6 +51,11 @@
   class OatDexFile {
    public:
     const OatClass GetOatClass(uint32_t class_def_index) const;
+
+    uint32_t GetDexFileChecksum() const {
+      return dex_file_checksum_;
+    }
+
     ~OatDexFile();
    private:
     OatDexFile(const OatFile* oat_file,
@@ -67,7 +72,7 @@
     DISALLOW_COPY_AND_ASSIGN(OatDexFile);
   };
 
-  const OatDexFile& GetOatDexFile(const DexFile& dex_file);
+  const OatDexFile& GetOatDexFile(const std::string& dex_file_location);
 
   size_t GetSize() const {
     return GetLimit() - GetBase();
diff --git a/src/oat_test.cc b/src/oat_test.cc
index b1453b3..c3d012e 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -35,7 +35,7 @@
   ByteArray* ame_stub_array = runtime->GetAbstractMethodErrorStubArray();
 
   const DexFile& dex_file = *java_lang_dex_file_.get();
-  const OatFile::OatDexFile& oat_dex_file = oat_file->GetOatDexFile(dex_file);
+  const OatFile::OatDexFile& oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation());
   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);
diff --git a/src/oatdump.cc b/src/oatdump.cc
index bec8d10..e96b25c 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -22,43 +22,21 @@
 static void usage() {
   fprintf(stderr,
           "Usage: oatdump [options] ...\n"
-          "    Example: oatdump --dex-file=$ANDROID_PRODUCT_OUT/system/framework/core.jar --oat=$ANDROID_PRODUCT_OUT/system/framework/boot.oat --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art --strip-prefix=$ANDROID_PRODUCT_OUT\n"
-          "    Example: adb shell oatdump --dex-file=/system/framework/core.jar --oat=/system/framework/boot.oat --image=/system/framework/boot.art\n"
-          "\n");
-  // TODO: remove this by inferring from --image or --oat
-  fprintf(stderr,
-          "  --dex-file=<dex-file>: specifies a .dex file location. At least one .dex\n"
-          "      file must be specified. \n"
-          "      Example: --dex-file=/system/framework/core.jar\n"
+          "    Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art --host-prefix=$ANDROID_PRODUCT_OUT\n"
+          "    Example: adb shell oatdump --image=/system/framework/boot.art\n"
           "\n");
   fprintf(stderr,
           "  --image=<file.art>: specifies the required input image filename.\n"
           "      Example: --image=/system/framework/boot.art\n"
           "\n");
-  // TODO: remove this by inferring from --image
-  fprintf(stderr,
-          "  --oat=<file.oat>: specifies the required input oat filename.\n"
-          "      Example: --image=/system/framework/boot.oat\n"
-          "\n");
   fprintf(stderr,
           "  --boot-image=<file.art>: provide the image file for the boot class path.\n"
           "      Example: --boot-image=/system/framework/boot.art\n"
           "\n");
-  // TODO: remove this by inferring from --boot-image
   fprintf(stderr,
-          "  --boot-oat=<file.oat>: provide the oat file for the boot class path.\n"
-          "      Example: --boot-oat=/system/framework/boot.oat\n"
-          "\n");
-  // TODO: remove this by inderring from --boot-image or --boot-oat
-  fprintf(stderr,
-          "  --boot-dex-file=<dex-file>: specifies a .dex file that is part of the boot\n"
-          "       image specified with --boot. \n"
-          "      Example: --boot-dex-file=/system/framework/core.jar\n"
-          "\n");
-  fprintf(stderr,
-          "  --strip-prefix may be used to strip a path prefix from dex file names in the\n"
-          "       the generated image to match the target file system layout.\n"
-          "      Example: --strip-prefix=out/target/product/crespo\n"
+          "  --host-prefix may be used to translate host paths to target paths during\n"
+          "      cross compilation.\n"
+          "      Example: --host-prefix=out/target/product/crespo\n"
           "\n");
   fprintf(stderr,
           "  --output=<file> may be used to send the output to a file.\n"
@@ -72,6 +50,7 @@
   "kAbstractMethodErrorStubArray",
   "kCalleeSaveMethod",
   "kOatLocation",
+  "kDexCaches",
 };
 
 class OatDump {
@@ -369,32 +348,20 @@
     usage();
   }
 
-  std::vector<const char*> dex_filenames;
   const char* image_filename = NULL;
-  const char* oat_filename = NULL;
   const char* boot_image_filename = NULL;
-  const char* boot_oat_filename = NULL;
-  std::vector<const char*> boot_dex_filenames;
-  std::string strip_location_prefix;
+  std::string host_prefix;
   std::ostream* os = &std::cout;
   UniquePtr<std::ofstream> out;
 
   for (int i = 0; i < argc; i++) {
     const StringPiece option(argv[i]);
-    if (option.starts_with("--dex-file=")) {
-      dex_filenames.push_back(option.substr(strlen("--dex-file=")).data());
-    } else if (option.starts_with("--image=")) {
+    if (option.starts_with("--image=")) {
       image_filename = option.substr(strlen("--image=")).data();
-    } else if (option.starts_with("--oat=")) {
-      oat_filename = option.substr(strlen("--oat=")).data();
     } else if (option.starts_with("--boot-image=")) {
       boot_image_filename = option.substr(strlen("--boot-image=")).data();
-    } else if (option.starts_with("--boot-oat=")) {
-      boot_oat_filename = option.substr(strlen("--boot-oat=")).data();
-    } else if (option.starts_with("--boot-dex-file=")) {
-      boot_dex_filenames.push_back(option.substr(strlen("--boot-dex-file=")).data());
-    } else if (option.starts_with("--strip-prefix=")) {
-      strip_location_prefix = option.substr(strlen("--strip-prefix=")).data();
+    } else if (option.starts_with("--host-prefix=")) {
+      host_prefix = option.substr(strlen("--host-prefix=")).data();
     } else if (option.starts_with("--output=")) {
       const char* filename = option.substr(strlen("--output=")).data();
       out.reset(new std::ofstream(filename));
@@ -414,69 +381,29 @@
    return EXIT_FAILURE;
   }
 
-  if (oat_filename == NULL) {
-   fprintf(stderr, "--oat file name not specified\n");
-   return EXIT_FAILURE;
-  }
-
-  if (dex_filenames.empty()) {
-   fprintf(stderr, "no --dex-file values specified\n");
-   return EXIT_FAILURE;
-  }
-
-  if ((boot_image_filename != NULL) != (boot_oat_filename != NULL)) {
-   fprintf(stderr, "--boot-image and --boat-oat must be specified together or not at all\n");
-   return EXIT_FAILURE;
-  }
-
-  if (boot_image_filename != NULL && boot_dex_filenames.empty()) {
-    fprintf(stderr, "no --boot-dex-file values specified with --boot\n");
-    return EXIT_FAILURE;
-  }
-
-  std::vector<const DexFile*> dex_files;
-  DexFile::OpenDexFiles(dex_filenames, dex_files, strip_location_prefix);
-
-  std::vector<const DexFile*> boot_dex_files;
-  DexFile::OpenDexFiles(boot_dex_filenames, boot_dex_files, strip_location_prefix);
-
   Runtime::Options options;
   std::string image_option;
   std::string oat_option;
   std::string boot_image_option;
   std::string boot_oat_option;
-  if (boot_image_filename == NULL) {
-    // if we don't have multiple images, pass the main one as the boot to match dex2oat
-    boot_image_filename = image_filename;
-    boot_oat_filename = oat_filename;
-    boot_dex_files = dex_files;
-    dex_files.clear();
-  } else {
-    image_option += "-Ximage:";
-    image_option += image_filename;
-    oat_option += "-Xoat:";
-    oat_option += oat_filename;
-    options.push_back(std::make_pair("classpath", &dex_files));
-    options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL)));
-    options.push_back(std::make_pair(oat_option.c_str(), reinterpret_cast<void*>(NULL)));
+  if (boot_image_filename != NULL) {
+    boot_image_option += "-Ximage:";
+    boot_image_option += boot_image_filename;
+    options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
   }
-  boot_image_option += "-Xbootimage:";
-  boot_image_option += boot_image_filename;
-  boot_oat_option += "-Xbootoat:";
-  boot_oat_option += boot_oat_filename;
-  options.push_back(std::make_pair("bootclasspath", &boot_dex_files));
-  options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
-  options.push_back(std::make_pair(boot_oat_option.c_str(), reinterpret_cast<void*>(NULL)));
+  image_option += "-Ximage:";
+  image_option += image_filename;
+  options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL)));
+
+  if (!host_prefix.empty()) {
+    options.push_back(std::make_pair("host-prefix", host_prefix.c_str()));
+  }
 
   UniquePtr<Runtime> runtime(Runtime::Create(options, false));
   if (runtime.get() == NULL) {
     fprintf(stderr, "could not create runtime\n");
     return EXIT_FAILURE;
   }
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  for (size_t i = 0; i < dex_files.size(); i++) {
-    class_linker->RegisterDexFile(*dex_files[i]);
-  }
 
   Space* image_space = Heap::GetSpaces()[Heap::GetSpaces().size()-2];
   CHECK(image_space != NULL);
diff --git a/src/runtime.cc b/src/runtime.cc
index 6cde082..a874464 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -16,7 +16,6 @@
 #include "oat_file.h"
 #include "signal_catcher.h"
 #include "space.h"
-#include "stl_util.h"
 #include "thread.h"
 #include "thread_list.h"
 
@@ -53,7 +52,6 @@
   // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
   delete thread_list_;
 
-  STLDeleteElements(&oat_files_);
   delete class_linker_;
   Heap::Destroy();
   delete intern_table_;
@@ -177,22 +175,16 @@
   }
 }
 
-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], "");
-    if (dex_file != NULL) {
-      class_path_vector.push_back(dex_file);
-    }
-  }
-}
-
 Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) {
   UniquePtr<ParsedOptions> parsed(new ParsedOptions());
-  parsed->boot_image_ = NULL;
-  parsed->boot_oat_ = NULL;
+  const char* boot_class_path = getenv("BOOTCLASSPATH");
+  if (boot_class_path != NULL) {
+    parsed->boot_class_path_ = getenv("BOOTCLASSPATH");
+  }
+  const char* class_path = getenv("CLASSPATH");
+  if (class_path != NULL) {
+    parsed->class_path_ = getenv("CLASSPATH");
+  }
 #ifdef NDEBUG
   // -Xcheck:jni is off by default for regular builds...
   parsed->check_jni_ = false;
@@ -211,35 +203,11 @@
 
   for (size_t i = 0; i < options.size(); ++i) {
     const StringPiece& option = options[i].first;
+    if (false) {
+      LOG(INFO) << "option[" << i << "]=" << option;
+    }
     if (option.starts_with("-Xbootclasspath:")) {
-      parsed->boot_class_path_string_ = option.substr(strlen("-Xbootclasspath:")).data();
-    } else if (option == "bootclasspath") {
-      UNIMPLEMENTED(WARNING) << "what should VMRuntime.getBootClassPath return here?";
-      const void* dex_vector = options[i].second;
-      const std::vector<const DexFile*>* v
-          = reinterpret_cast<const std::vector<const DexFile*>*>(dex_vector);
-      if (v == NULL) {
-        if (ignore_unrecognized) {
-          continue;
-        }
-        // TODO: usage
-        LOG(FATAL) << "Failed to parse " << option;
-        return NULL;
-      }
-      parsed->boot_class_path_ = *v;
-    } else if (option == "classpath") {
-      const void* dex_vector = options[i].second;
-      const std::vector<const DexFile*>* v
-          = reinterpret_cast<const std::vector<const DexFile*>*>(dex_vector);
-      if (v == NULL) {
-        if (ignore_unrecognized) {
-          continue;
-        }
-        // TODO: usage
-        LOG(FATAL) << "Failed to parse " << option;
-        return NULL;
-      }
-      parsed->class_path_ = *v;
+      parsed->boot_class_path_ = option.substr(strlen("-Xbootclasspath:")).data();
     } else if (option == "-classpath" || option == "-cp") {
       // TODO: support -Djava.class.path
       i++;
@@ -249,17 +217,9 @@
         return NULL;
       }
       const StringPiece& value = options[i].first;
-      parsed->class_path_string_ = value.data();
-    } else if (option.starts_with("-Xbootimage:")) {
-      // TODO: remove and just use -Ximage:
-      parsed->boot_image_ = option.substr(strlen("-Xbootimage:")).data();
-    } else if (option.starts_with("-Xbootoat:")) {
-      // TODO: remove and just use -Xoat:
-      parsed->boot_oat_ = option.substr(strlen("-Xbootoat:")).data();
+      parsed->class_path_ = value.data();
     } else if (option.starts_with("-Ximage:")) {
       parsed->images_.push_back(option.substr(strlen("-Ximage:")).data());
-    } else if (option.starts_with("-Xoat:")) {
-      parsed->oats_.push_back(option.substr(strlen("-Xoat:")).data());
     } else if (option.starts_with("-Xcheck:jni")) {
       parsed->check_jni_ = true;
     } else if (option.starts_with("-Xms")) {
@@ -311,6 +271,8 @@
       parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(options[i].second);
     } else if (option == "abort") {
       parsed->hook_abort_ = reinterpret_cast<void(*)()>(options[i].second);
+    } else if (option == "host-prefix") {
+      parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second);
     } else {
       if (!ignore_unrecognized) {
         // TODO: print usage via vfprintf
@@ -321,38 +283,6 @@
     }
   }
 
-  // Consider it an error if both bootclasspath and -Xbootclasspath: are supplied.
-  // TODO: remove bootclasspath and classpath which are mostly just used by tests?
-  if (!parsed->boot_class_path_.empty() && !parsed->boot_class_path_string_.empty()) {
-    // TODO: usage
-    LOG(FATAL) << "bootclasspath and -Xbootclasspath: are mutually exclusive options.";
-    return NULL;
-  }
-  if (!parsed->class_path_.empty() && !parsed->class_path_string_.empty()) {
-    // TODO: usage
-    LOG(FATAL) << "bootclasspath and -Xbootclasspath: are mutually exclusive options.";
-    return NULL;
-  }
-  if (parsed->boot_class_path_.empty()) {
-    if (parsed->boot_class_path_string_ == NULL) {
-      const char* BOOTCLASSPATH = getenv("BOOTCLASSPATH");
-      if (BOOTCLASSPATH != NULL) {
-        parsed->boot_class_path_string_ = BOOTCLASSPATH;
-      }
-    }
-    CreateClassPath(parsed->boot_class_path_string_, parsed->boot_class_path_);
-  }
-
-  if (parsed->class_path_.empty()) {
-    if (parsed->class_path_string_ == NULL) {
-      const char* CLASSPATH = getenv("CLASSPATH");
-      if (CLASSPATH != NULL) {
-        parsed->class_path_string_ = CLASSPATH;
-      }
-    }
-    CreateClassPath(parsed->class_path_string_, parsed->class_path_);
-  }
-
   LOG(INFO) << "CheckJNI is " << (parsed->check_jni_ ? "on" : "off");
 
   return parsed.release();
@@ -375,6 +305,9 @@
   if (IsVerboseStartup()) {
     LOG(INFO) << "Runtime::Start entering";
   }
+
+  CHECK(host_prefix_.empty()) << host_prefix_;
+
   InitNativeMethods();
 
   Thread::FinishStartup();
@@ -405,7 +338,7 @@
   env->CallStaticVoidMethod(c, mid);
 }
 
-bool Runtime::IsStarted() {
+bool Runtime::IsStarted() const {
   return started_;
 }
 
@@ -422,8 +355,9 @@
     LOG(INFO) << "Runtime::Init -verbose:startup enabled";
   }
 
-  boot_class_path_ = options->boot_class_path_string_;
-  class_path_ = options->class_path_string_;
+  host_prefix_ = options->host_prefix_;
+  boot_class_path_ = options->boot_class_path_;
+  class_path_ = options->class_path_;
   properties_ = options->properties_;
 
   vfprintf_ = options->hook_vfprintf_;
@@ -435,8 +369,7 @@
   thread_list_ = new ThreadList(options->IsVerbose("thread"));
   intern_table_ = new InternTable;
 
-  Heap::Init(options->heap_initial_size_, options->heap_maximum_size_,
-             options->boot_image_, options->images_);
+  Heap::Init(options->heap_initial_size_, options->heap_maximum_size_, options->images_);
 
   BlockSignals();
 
@@ -448,22 +381,10 @@
   // without creating objects.
   Thread::Attach(this, "main", false);
 
-  class_linker_ = ClassLinker::Create(options->boot_class_path_,
-                                      options->class_path_,
-                                      intern_table_,
-                                      Heap::GetBootSpace() != NULL);
-  if (Heap::GetBootSpace() != NULL) {
-    if (!OpenOat(Heap::GetBootSpace(), options->boot_oat_)) {
-      LOG(ERROR) << "Failed to open boot oat " << options->boot_oat_;
-      return false;
-    }
-  }
-  for (size_t i = 0; i < options->oats_.size(); i++) {
-    if (!OpenOat(Heap::GetSpaces()[i+1], options->oats_[i])) {
-      LOG(ERROR) << "Failed to open oat " << options->oats_[i];
-      return false;
-    }
-  }
+  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 (IsVerboseStartup()) {
     LOG(INFO) << "Runtime::Init exiting";
@@ -471,49 +392,6 @@
   return true;
 }
 
-bool Runtime::OpenOat(const Space* space, const char* oat) {
-  if (IsVerboseStartup()) {
-    LOG(INFO) << "Runtime::OpenOat entering " << oat;
-  }
-  // TODO: check in ParsedOptions?
-  if (space == NULL) {
-    LOG(ERROR) << "oat specified without image";
-    return false;
-  }
-  if (oat == NULL) {
-    LOG(ERROR) << "image specified without oat";
-    return false;
-  }
-  const ImageHeader& image_header = space->GetImageHeader();
-  String* oat_location = image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString();
-  std::string oat_filename = oat_location->ToModifiedUtf8();
-  if (!StringPiece(oat).ends_with(oat_filename)) {
-    LOG(ERROR) << "oat file name " << oat
-               << " does not match value found in image: " << oat_filename;
-    return false;
-  }
-  // TODO: we should be able to just use oat_filename instead of oat
-  // if we passed the prefix argument to find it on the host during cross compilation.
-  OatFile* oat_file = OatFile::Open(std::string(oat), "", image_header.GetOatBaseAddr());
-  if (oat_file == NULL) {
-    LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image";
-    return false;
-  }
-  uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
-  uint32_t image_oat_checksum = image_header.GetOatChecksum();
-  if (oat_checksum != image_oat_checksum) {
-    LOG(ERROR) << "Failed to match oat filechecksum " << std::hex << oat_checksum
-               << " to expected oat checksum " << std::hex << oat_checksum
-               << " in image";
-    return false;
-  }
-  oat_files_.push_back(oat_file);
-  if (IsVerboseStartup()) {
-    LOG(INFO) << "Runtime::OpenOat exiting";
-  }
-  return true;
-}
-
 void Runtime::InitNativeMethods() {
   if (IsVerboseStartup()) {
     LOG(INFO) << "Runtime::InitNativeMethods entering";
diff --git a/src/runtime.h b/src/runtime.h
index bae5643..bd2c7a2 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -30,7 +30,6 @@
 class InternTable;
 class JavaVMExt;
 class Method;
-class OatFile;
 class SignalCatcher;
 class String;
 class ThreadList;
@@ -45,14 +44,10 @@
     // returns null if problem parsing and ignore_unrecognized is false
     static ParsedOptions* Create(const Options& options, bool ignore_unrecognized);
 
-    std::string boot_class_path_string_;
-    std::vector<const DexFile*> boot_class_path_;
-    std::string class_path_string_;
-    std::vector<const DexFile*> class_path_;
-    const char* boot_image_;
-    const char* boot_oat_;
-    std::vector<const char*> images_;
-    std::vector<const char*> oats_;
+    std::string boot_class_path_;
+    std::string class_path_;
+    std::string host_prefix_;
+    std::vector<std::string> images_;
     bool check_jni_;
     std::string jni_trace_;
     size_t heap_initial_size_;
@@ -79,10 +74,15 @@
     return verbose_startup_;
   }
 
+  const std::string& GetHostPrefix() const {
+    CHECK(!IsStarted());
+    return host_prefix_;
+  }
+
   // Starts a runtime, which may cause threads to be started and code to run.
   void Start();
 
-  bool IsStarted();
+  bool IsStarted() const;
 
   static Runtime* Current() {
     return instance_;
@@ -182,13 +182,24 @@
   void BlockSignals();
 
   bool Init(const Options& options, bool ignore_unrecognized);
-  bool OpenOat(const Space* space, const char* boot_oat_);
   void InitNativeMethods();
   void RegisterRuntimeNativeMethods(JNIEnv*);
   void StartDaemonThreads();
 
   bool verbose_startup_;
 
+  // The host prefix is used during cross compilation. It is removed
+  // from the start of host paths such as:
+  //    $ANDROID_PRODUCT_OUT/system/framework/core.oat
+  // to produce target paths such as 
+  //    /system/framework/core.oat
+  // Similarly it is prepended to target paths to arrive back at a
+  // host past. In both cases this is necessary because image and oat
+  // files embedded expect paths of dependent files (an image points
+  // to an oat file and an oat files to one or more dex files). These
+  // files contain the expected target path.
+  std::string host_prefix_;
+
   std::string boot_class_path_;
   std::string class_path_;
   std::vector<std::string> properties_;
@@ -202,8 +213,6 @@
 
   ClassLinker* class_linker_;
 
-  std::vector<const OatFile*> oat_files_;
-
   SignalCatcher* signal_catcher_;
 
   JavaVMExt* java_vm_;
diff --git a/src/runtime_test.cc b/src/runtime_test.cc
index 66c181b..ce03571 100644
--- a/src/runtime_test.cc
+++ b/src/runtime_test.cc
@@ -27,7 +27,7 @@
   options.push_back(std::make_pair(lib_core.c_str(), null));
   options.push_back(std::make_pair("-cp", null));
   options.push_back(std::make_pair(lib_core.c_str(), null));
-  options.push_back(std::make_pair("-Xbootimage:boot_image", null));
+  options.push_back(std::make_pair("-Ximage:boot_image", null));
   options.push_back(std::make_pair("-Ximage:image_1", null));
   options.push_back(std::make_pair("-Ximage:image_2", null));
   options.push_back(std::make_pair("-Xcheck:jni", null));
@@ -37,22 +37,24 @@
   options.push_back(std::make_pair("-Dfoo=bar", null));
   options.push_back(std::make_pair("-Dbaz=qux", null));
   options.push_back(std::make_pair("-verbose:gc,class,jni", null));
+  options.push_back(std::make_pair("host-prefix", "host_prefix"));
   options.push_back(std::make_pair("vfprintf", test_vfprintf));
   options.push_back(std::make_pair("abort", test_abort));
   options.push_back(std::make_pair("exit", test_exit));
   UniquePtr<Runtime::ParsedOptions> parsed(Runtime::ParsedOptions::Create(options, false));
   ASSERT_TRUE(parsed.get() != NULL);
 
-  EXPECT_EQ(1U, parsed->boot_class_path_.size());
-  EXPECT_EQ(1U, parsed->class_path_.size());
-  EXPECT_STREQ("boot_image", parsed->boot_image_);
-  EXPECT_EQ(2U, parsed->images_.size());
-  EXPECT_STREQ("image_1", parsed->images_[0]);
-  EXPECT_STREQ("image_2", parsed->images_[1]);
+  EXPECT_EQ(lib_core, parsed->boot_class_path_);
+  EXPECT_EQ(lib_core, parsed->class_path_);
+  EXPECT_EQ(3U, parsed->images_.size());
+  EXPECT_EQ(std::string("boot_image"), parsed->images_[0]);
+  EXPECT_EQ(std::string("image_1"), parsed->images_[1]);
+  EXPECT_EQ(std::string("image_2"), parsed->images_[2]);
   EXPECT_EQ(true, parsed->check_jni_);
   EXPECT_EQ(2048U, parsed->heap_initial_size_);
   EXPECT_EQ(4 * KB, parsed->heap_maximum_size_);
   EXPECT_EQ(1 * MB, parsed->stack_size_);
+  EXPECT_EQ("host_prefix", parsed->host_prefix_);
   EXPECT_TRUE(test_vfprintf == parsed->hook_vfprintf_);
   EXPECT_TRUE(test_exit == parsed->hook_exit_);
   EXPECT_TRUE(test_abort == parsed->hook_abort_);
diff --git a/src/space.cc b/src/space.cc
index 09eb0c9..08d758a 100644
--- a/src/space.cc
+++ b/src/space.cc
@@ -24,7 +24,7 @@
   }
 }
 
-Space* Space::CreateFromImage(const char* image_file_name) {
+Space* Space::CreateFromImage(const std::string& image_file_name) {
   CHECK(image_file_name != NULL);
   UniquePtr<Space> space(new Space());
   bool success = space->InitFromImage(image_file_name);
@@ -97,13 +97,13 @@
 }
 
 
-bool Space::InitFromImage(const char* image_file_name) {
+bool Space::InitFromImage(const std::string& image_file_name) {
   const Runtime* runtime = Runtime::Current();
   if (runtime->IsVerboseStartup()) {
     LOG(INFO) << "Space::InitFromImage entering"
               << " image_file_name=" << image_file_name;
   }
-  UniquePtr<File> file(OS::OpenFile(image_file_name, false));
+  UniquePtr<File> file(OS::OpenFile(image_file_name.c_str(), false));
   if (file.get() == NULL) {
     LOG(WARNING) << "Failed to open " << image_file_name;
     return false;
diff --git a/src/space.h b/src/space.h
index 1536c27..1e2a58b 100644
--- a/src/space.h
+++ b/src/space.h
@@ -23,7 +23,7 @@
   static Space* Create(size_t initial_size, size_t maximum_size, byte* requested_base);
 
   // create a Space from an image file. cannot be used for future allocation or collected.
-  static Space* CreateFromImage(const char* image);
+  static Space* CreateFromImage(const std::string& image);
 
   ~Space();
 
@@ -51,8 +51,12 @@
     return limit_ - base_;
   }
 
+  bool IsImageSpace() const {
+    return (image_header_ != NULL);
+  }
+
   const ImageHeader& GetImageHeader() const {
-    CHECK(image_header_ != NULL);
+    CHECK(IsImageSpace());
     return *image_header_;
   }
 
@@ -78,7 +82,7 @@
   void Init(MemMap* map);
 
   // Initializes the space from an image file
-  bool InitFromImage(const char* image_file_name);
+  bool InitFromImage(const std::string& image_file_name);
 
   void* CreateMallocSpace(void* base, size_t initial_size, size_t maximum_size);
 
diff --git a/test/003-omnibus-opcodes/build b/test/003-omnibus-opcodes/build
index bbd392f..c3af10c 100644
--- a/test/003-omnibus-opcodes/build
+++ b/test/003-omnibus-opcodes/build
@@ -26,10 +26,8 @@
 zip ${ANDROID_PRODUCT_OUT}/system/framework/test.jar classes.dex
 
 dex2oatd -Xms16m -Xmx16m \
-    --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \
-    --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \
     --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \
     --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test.jar \
     --oat=${ANDROID_PRODUCT_OUT}/system/framework/test.oat \
     --image=${ANDROID_PRODUCT_OUT}/system/framework/test.art \
-    --strip-prefix=${ANDROID_PRODUCT_OUT}
+    --host-prefix=${ANDROID_PRODUCT_OUT}
diff --git a/test/023-many-interfaces/build b/test/023-many-interfaces/build
index 118e178..d0f376c 100644
--- a/test/023-many-interfaces/build
+++ b/test/023-many-interfaces/build
@@ -28,10 +28,8 @@
 zip ${ANDROID_PRODUCT_OUT}/system/framework/test.jar classes.dex
 
 dex2oatd -Xms16m -Xmx16m \
-    --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \
-    --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \
     --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \
     --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test.jar \
     --oat=${ANDROID_PRODUCT_OUT}/system/framework/test.oat \
     --image=${ANDROID_PRODUCT_OUT}/system/framework/test.art \
-    --strip-prefix=${ANDROID_PRODUCT_OUT}
+    --host-prefix=${ANDROID_PRODUCT_OUT}
diff --git a/test/056-const-string-jumbo/build b/test/056-const-string-jumbo/build
index c39779b..a780c13 100644
--- a/test/056-const-string-jumbo/build
+++ b/test/056-const-string-jumbo/build
@@ -47,10 +47,8 @@
 zip ${ANDROID_PRODUCT_OUT}/system/framework/test.jar classes.dex
 
 dex2oatd -Xms16m -Xmx16m \
-    --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \
-    --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \
     --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \
     --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test.jar \
     --oat=${ANDROID_PRODUCT_OUT}/system/framework/test.oat \
     --image=${ANDROID_PRODUCT_OUT}/system/framework/test.art \
-    --strip-prefix=${ANDROID_PRODUCT_OUT}
+    --host-prefix=${ANDROID_PRODUCT_OUT}
diff --git a/test/085-old-style-inner-class/build b/test/085-old-style-inner-class/build
index 5a1b04c..d3dc15f 100644
--- a/test/085-old-style-inner-class/build
+++ b/test/085-old-style-inner-class/build
@@ -29,10 +29,8 @@
 zip ${ANDROID_PRODUCT_OUT}/system/framework/test.jar classes.dex
 
 dex2oatd -Xms16m -Xmx16m \
-    --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \
-    --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \
     --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \
     --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test.jar \
     --oat=${ANDROID_PRODUCT_OUT}/system/framework/test.oat \
     --image=${ANDROID_PRODUCT_OUT}/system/framework/test.art \
-    --strip-prefix=${ANDROID_PRODUCT_OUT}
+    --host-prefix=${ANDROID_PRODUCT_OUT}
diff --git a/test/etc/default-build b/test/etc/default-build
index e31e0ea..0ef8ba8 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -29,13 +29,11 @@
 zip ${ANDROID_PRODUCT_OUT}/system/framework/test.jar classes.dex
 
 dex2oatd -Xms16m -Xmx16m \
-    --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \
-    --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \
     --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \
     --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test.jar \
     --oat=${ANDROID_PRODUCT_OUT}/system/framework/test.oat \
     --image=${ANDROID_PRODUCT_OUT}/system/framework/test.art \
-    --strip-prefix=${ANDROID_PRODUCT_OUT}
+    --host-prefix=${ANDROID_PRODUCT_OUT}
 
 if [ -r src-ex ]; then
     mkdir classes-ex
@@ -51,11 +49,9 @@
     mv classes-1.dex classes.dex
 
     dex2oatd -Xms16m -Xmx16m \
-        --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \
-        --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \
         --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \
         --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test-ex.jar \
         --oat=${ANDROID_PRODUCT_OUT}/system/framework/test-ex.oat \
         --image=${ANDROID_PRODUCT_OUT}/system/framework/test-ex.art \
-        --strip-prefix=${ANDROID_PRODUCT_OUT}
+        --host-prefix=${ANDROID_PRODUCT_OUT}
 fi
diff --git a/test/etc/push-and-run-test-jar b/test/etc/push-and-run-test-jar
index fd96b6b..0d4e3b4 100755
--- a/test/etc/push-and-run-test-jar
+++ b/test/etc/push-and-run-test-jar
@@ -135,11 +135,7 @@
     adb shell cd /data \; dvz -classpath test.jar Main "$@"
 else
     cmdline="cd /data; oatexecd \
-      -Xbootclasspath:/system/framework/core.jar \
-      -Xbootoat:/system/framework/core.oat \
-      -Xbootimage:/system/framework/core.art \
-      -classpath /system/framework/test.jar \
-      -Xoat:/system/framework/test.oat \
+      -Ximage:/system/framework/core.art \
       -Ximage:/system/framework/test.art Main"
     #cmdline="cd /data; dalvikvm $DEX_VERIFY $DEX_OPTIMIZE $DEX_DEBUG \
     #    $GC_OPTS -cp test.jar -Xint:${INTERP} -ea Main"