Address some comments in image writer

Change-Id: I74c3192d595dc8b86d6ce3e3ca3bb32cce61872c
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index f9f0eb8..fce08ea 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -1221,8 +1221,11 @@
     // Compiling the boot image, add null class loader.
     class_loaders_.insert(nullptr);
   }
-  if (!class_loaders_.empty()) {
-    CHECK_EQ(class_loaders_.size(), 1u) << "Should only have one real class loader in the image";
+  // class_loaders_ usually will not be empty, but may be empty if we attempt to create an image
+  // with no classes.
+  if (class_loaders_.size() == 1u) {
+    // Only write the class table if we have exactly one class loader. There may be cases where
+    // there are multiple class loaders if a class path is passed to dex2oat.
     ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
     for (mirror::ClassLoader* loader : class_loaders_) {
       ClassTable* table = class_linker->ClassTableForClassLoader(loader);
@@ -1424,28 +1427,32 @@
   CHECK_EQ(temp_intern_table.Size(), intern_table->Size());
   temp_intern_table.VisitRoots(&root_visitor, kVisitRootFlagAllRoots);
 
-  // Write the class table(s) into the image.
-  ClassLinker* const class_linker = runtime->GetClassLinker();
-  const ImageSection& class_table_section = image_header->GetImageSection(
-      ImageHeader::kSectionClassTable);
-  uint8_t* const class_table_memory_ptr = image_->Begin() + class_table_section.Offset();
-  ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
-  size_t class_table_bytes = 0;
-  for (mirror::ClassLoader* loader : class_loaders_) {
-    ClassTable* table = class_linker->ClassTableForClassLoader(loader);
-    CHECK(table != nullptr);
-    uint8_t* memory_ptr = class_table_memory_ptr + class_table_bytes;
-    class_table_bytes += table->WriteToMemory(memory_ptr);
-    // Fixup the pointers in the newly written class table to contain image addresses. See
-    // above comment for intern tables.
-    ClassTable temp_class_table;
-    temp_class_table.ReadFromMemory(memory_ptr);
-    // CHECK_EQ(temp_class_table.NumNonZygoteClasses(), table->NumNonZygoteClasses());
-    BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(&root_visitor,
-                                                                    RootInfo(kRootUnknown));
-    temp_class_table.VisitRoots(buffered_visitor);
+  // Write the class table(s) into the image. class_table_bytes_ may be 0 if there are multiple
+  // class loaders. Writing multiple class tables into the image is currently unsupported.
+  if (class_table_bytes_ > 0u) {
+    ClassLinker* const class_linker = runtime->GetClassLinker();
+    const ImageSection& class_table_section = image_header->GetImageSection(
+        ImageHeader::kSectionClassTable);
+    uint8_t* const class_table_memory_ptr = image_->Begin() + class_table_section.Offset();
+    ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+    size_t class_table_bytes = 0;
+    for (mirror::ClassLoader* loader : class_loaders_) {
+      ClassTable* table = class_linker->ClassTableForClassLoader(loader);
+      CHECK(table != nullptr);
+      uint8_t* memory_ptr = class_table_memory_ptr + class_table_bytes;
+      class_table_bytes += table->WriteToMemory(memory_ptr);
+      // Fixup the pointers in the newly written class table to contain image addresses. See
+      // above comment for intern tables.
+      ClassTable temp_class_table;
+      temp_class_table.ReadFromMemory(memory_ptr);
+      CHECK_EQ(temp_class_table.NumZygoteClasses(), table->NumNonZygoteClasses() +
+               table->NumZygoteClasses());
+      BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(&root_visitor,
+                                                                      RootInfo(kRootUnknown));
+      temp_class_table.VisitRoots(buffered_visitor);
+    }
+    CHECK_EQ(class_table_bytes, class_table_bytes_);
   }
-  CHECK_EQ(class_table_bytes, class_table_bytes_);
 }
 
 void ImageWriter::CopyAndFixupObjects() {
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index c20d836..8e930f0 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -457,7 +457,9 @@
   // Prune class memoization table to speed up ContainsBootClassLoaderNonImageClass.
   std::unordered_map<mirror::Class*, bool> prune_class_memo_;
 
-  // Class loaders with a class table to write out. Should only be one currently.
+  // Class loaders with a class table to write out. There should only be one class loader because
+  // dex2oat loads the dex files to be compiled into a single class loader. For the boot image,
+  // null is a valid entry.
   std::unordered_set<mirror::ClassLoader*> class_loaders_;
 
   // Number of image class table bytes.
diff --git a/runtime/image.h b/runtime/image.h
index 3032beb..7418f66 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -262,7 +262,7 @@
   // Boolean (0 or 1) to denote if the image was compiled with --compile-pic option
   const uint32_t compile_pic_;
 
-  // Image sections
+  // Image section sizes/offsets correspond to the uncompressed form.
   ImageSection sections_[kSectionCount];
 
   // Image methods.