Throw IOException at source of failing to open a dex file.
Before is:
java.lang.ClassNotFoundException: Didn't find class "GCBench" on path: DexPathList[[zip file "/disk2/dalvik-dev/out/host/linux-x86/framework/GCBench.jar"],nativeLibraryDirectories=[/disk2/dalvik-dev/out/host/linux-x86/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
Suppressed: java.lang.ClassNotFoundException: GCBench
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 1 more
Caused by: java.lang.NoClassDefFoundError: Class "LGCBench;" not found
... 5 more
And after is:
java.lang.ClassNotFoundException: Didn't find class "GCBench" on path: DexPathList[[zip file "/disk2/dalvik-dev/out/host/linux-x86/framework/GCBench.jar"],nativeLibraryDirectories=[/disk2/dalvik-dev/out/host/linux-x86/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
Suppressed: java.io.IOException: Zip archive '/disk2/dalvik-dev/out/host/linux-x86/framework/GCBench.jar' doesn't contain classes.dex
at dalvik.system.DexFile.openDexFile(Native Method)
at dalvik.system.DexFile.<init>(DexFile.java:80)
at dalvik.system.DexFile.<init>(DexFile.java:59)
at dalvik.system.DexPathList.loadDexFile(DexPathList.java:268)
at dalvik.system.DexPathList.makeDexElements(DexPathList.java:235)
at dalvik.system.DexPathList.<init>(DexPathList.java:113)
at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:48)
at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:38)
at java.lang.ClassLoader.createSystemClassLoader(ClassLoader.java:128)
at java.lang.ClassLoader.access$000(ClassLoader.java:65)
at java.lang.ClassLoader$SystemClassLoader.<clinit>(ClassLoader.java:81)
at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:137)
Suppressed: java.lang.ClassNotFoundException: GCBench
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 1 more
Caused by: java.lang.NoClassDefFoundError: Class "LGCBench;" not found
... 5 more
Also, move dex file verifier messages out of logs.
In the process the ClassLinker::dex_lock_ needed tidying to cover a smaller
scope. Bug 11301553.
Change-Id: I80058652e11e7ea63457cc01a0cb48afe1c15543
diff --git a/runtime/gc/accounting/atomic_stack.h b/runtime/gc/accounting/atomic_stack.h
index 997d725..8fa5b86 100644
--- a/runtime/gc/accounting/atomic_stack.h
+++ b/runtime/gc/accounting/atomic_stack.h
@@ -163,8 +163,10 @@
// Size in number of elements.
void Init() {
- mem_map_.reset(MemMap::MapAnonymous(name_.c_str(), NULL, capacity_ * sizeof(T), PROT_READ | PROT_WRITE));
- CHECK(mem_map_.get() != NULL) << "couldn't allocate mark stack";
+ std::string error_msg;
+ mem_map_.reset(MemMap::MapAnonymous(name_.c_str(), NULL, capacity_ * sizeof(T),
+ PROT_READ | PROT_WRITE, &error_msg));
+ CHECK(mem_map_.get() != NULL) << "couldn't allocate mark stack.\n" << error_msg;
byte* addr = mem_map_->Begin();
CHECK(addr != NULL);
debug_is_sorted_ = true;
diff --git a/runtime/gc/accounting/card_table.cc b/runtime/gc/accounting/card_table.cc
index 85034a0..7818bc8 100644
--- a/runtime/gc/accounting/card_table.cc
+++ b/runtime/gc/accounting/card_table.cc
@@ -54,9 +54,11 @@
/* Set up the card table */
size_t capacity = heap_capacity / kCardSize;
/* Allocate an extra 256 bytes to allow fixed low-byte of base */
+ std::string error_msg;
UniquePtr<MemMap> mem_map(MemMap::MapAnonymous("card table", NULL,
- capacity + 256, PROT_READ | PROT_WRITE));
- CHECK(mem_map.get() != NULL) << "couldn't allocate card table";
+ capacity + 256, PROT_READ | PROT_WRITE,
+ &error_msg));
+ CHECK(mem_map.get() != NULL) << "couldn't allocate card table: " << error_msg;
// All zeros is the correct initial value; all clean. Anonymous mmaps are initialized to zero, we
// don't clear the card table to avoid unnecessary pages being allocated
COMPILE_ASSERT(kCardClean == 0, card_clean_must_be_0);
diff --git a/runtime/gc/accounting/gc_allocator.cc b/runtime/gc/accounting/gc_allocator.cc
index 11d0e67..49d84fa 100644
--- a/runtime/gc/accounting/gc_allocator.cc
+++ b/runtime/gc/accounting/gc_allocator.cc
@@ -22,15 +22,17 @@
namespace art {
namespace gc {
namespace accounting {
- void* RegisterGCAllocation(size_t bytes) {
- Runtime::Current()->GetHeap()->RegisterGCAllocation(bytes);
- return malloc(bytes);
- }
- void RegisterGCDeAllocation(void* p, size_t bytes) {
- Runtime::Current()->GetHeap()->RegisterGCDeAllocation(bytes);
- free(p);
- }
+void* RegisterGcAllocation(size_t bytes) {
+ Runtime::Current()->GetHeap()->RegisterGCAllocation(bytes);
+ return malloc(bytes);
+}
+
+void RegisterGcDeallocation(void* p, size_t bytes) {
+ Runtime::Current()->GetHeap()->RegisterGCDeAllocation(bytes);
+ free(p);
+}
+
} // namespace accounting
} // namespace gc
} // namespace art
diff --git a/runtime/gc/accounting/gc_allocator.h b/runtime/gc/accounting/gc_allocator.h
index 1fba858..4fe9367 100644
--- a/runtime/gc/accounting/gc_allocator.h
+++ b/runtime/gc/accounting/gc_allocator.h
@@ -26,55 +26,56 @@
namespace art {
namespace gc {
namespace accounting {
- void* RegisterGCAllocation(size_t bytes);
- void RegisterGCDeAllocation(void* p, size_t bytes);
- static const bool kMeasureGCMemoryOverhead = false;
+void* RegisterGcAllocation(size_t bytes);
+void RegisterGcDeallocation(void* p, size_t bytes);
- template <typename T>
- class GCAllocatorImpl : public std::allocator<T> {
- public:
- typedef typename std::allocator<T>::value_type value_type;
- typedef typename std::allocator<T>::size_type size_type;
- typedef typename std::allocator<T>::difference_type difference_type;
- typedef typename std::allocator<T>::pointer pointer;
- typedef typename std::allocator<T>::const_pointer const_pointer;
- typedef typename std::allocator<T>::reference reference;
- typedef typename std::allocator<T>::const_reference const_reference;
+static const bool kMeasureGcMemoryOverhead = false;
- // Used internally by STL data structures.
- template <class U>
- GCAllocatorImpl(const GCAllocatorImpl<U>& alloc) throw() {
- }
+template <typename T>
+class GcAllocatorImpl : public std::allocator<T> {
+ public:
+ typedef typename std::allocator<T>::value_type value_type;
+ typedef typename std::allocator<T>::size_type size_type;
+ typedef typename std::allocator<T>::difference_type difference_type;
+ typedef typename std::allocator<T>::pointer pointer;
+ typedef typename std::allocator<T>::const_pointer const_pointer;
+ typedef typename std::allocator<T>::reference reference;
+ typedef typename std::allocator<T>::const_reference const_reference;
- // Used internally by STL data structures.
- GCAllocatorImpl() throw() {
- }
+ // Used internally by STL data structures.
+ template <class U>
+ GcAllocatorImpl(const GcAllocatorImpl<U>& alloc) throw() {
+ }
- // Enables an allocator for objects of one type to allocate storage for objects of another type.
- // Used internally by STL data structures.
- template <class U>
- struct rebind {
- typedef GCAllocatorImpl<U> other;
- };
+ // Used internally by STL data structures.
+ GcAllocatorImpl() throw() {
+ }
- pointer allocate(size_type n, const_pointer hint = 0) {
- return reinterpret_cast<pointer>(RegisterGCAllocation(n * sizeof(T)));
- }
-
- template <typename PT>
- void deallocate(PT p, size_type n) {
- RegisterGCDeAllocation(p, n * sizeof(T));
- }
+ // Enables an allocator for objects of one type to allocate storage for objects of another type.
+ // Used internally by STL data structures.
+ template <class U>
+ struct rebind {
+ typedef GcAllocatorImpl<U> other;
};
- // C++ doesn't allow template typedefs. This is a workaround template typedef which is
- // GCAllocatorImpl<T> if kMeasureGCMemoryOverhead is true, std::allocator<T> otherwise.
- template <typename T>
- class GCAllocator : public TypeStaticIf<kMeasureGCMemoryOverhead,
- GCAllocatorImpl<T>,
- std::allocator<T> >::value {
- };
+ pointer allocate(size_type n, const_pointer hint = 0) {
+ return reinterpret_cast<pointer>(RegisterGcAllocation(n * sizeof(T)));
+ }
+
+ template <typename PT>
+ void deallocate(PT p, size_type n) {
+ RegisterGcDeallocation(p, n * sizeof(T));
+ }
+};
+
+// C++ doesn't allow template typedefs. This is a workaround template typedef which is
+// GCAllocatorImpl<T> if kMeasureGCMemoryOverhead is true, std::allocator<T> otherwise.
+template <typename T>
+class GcAllocator : public TypeStaticIf<kMeasureGcMemoryOverhead, GcAllocatorImpl<T>,
+ std::allocator<T> >::value {
+};
+
} // namespace accounting
} // namespace gc
} // namespace art
diff --git a/runtime/gc/accounting/heap_bitmap.h b/runtime/gc/accounting/heap_bitmap.h
index 2ca8c4a..24ebbaa 100644
--- a/runtime/gc/accounting/heap_bitmap.h
+++ b/runtime/gc/accounting/heap_bitmap.h
@@ -31,8 +31,8 @@
class HeapBitmap {
public:
- typedef std::vector<SpaceBitmap*, GCAllocator<SpaceBitmap*> > SpaceBitmapVector;
- typedef std::vector<SpaceSetMap*, GCAllocator<SpaceSetMap*> > SpaceSetMapVector;
+ typedef std::vector<SpaceBitmap*, GcAllocator<SpaceBitmap*> > SpaceBitmapVector;
+ typedef std::vector<SpaceSetMap*, GcAllocator<SpaceSetMap*> > SpaceSetMapVector;
bool Test(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
SpaceBitmap* bitmap = GetContinuousSpaceBitmap(obj);
diff --git a/runtime/gc/accounting/mod_union_table.h b/runtime/gc/accounting/mod_union_table.h
index d874c60..5a99f1b 100644
--- a/runtime/gc/accounting/mod_union_table.h
+++ b/runtime/gc/accounting/mod_union_table.h
@@ -51,7 +51,7 @@
// cleared between GC phases, reducing the number of dirty cards that need to be scanned.
class ModUnionTable {
public:
- typedef std::set<byte*, std::less<byte*>, GCAllocator<byte*> > CardSet;
+ typedef std::set<byte*, std::less<byte*>, GcAllocator<byte*> > CardSet;
explicit ModUnionTable(const std::string& name, Heap* heap, space::ContinuousSpace* space)
: name_(name),
@@ -125,7 +125,7 @@
// Maps from dirty cards to their corresponding alloc space references.
SafeMap<const byte*, std::vector<mirror::Object**>, std::less<const byte*>,
- GCAllocator<std::pair<const byte*, std::vector<mirror::Object**> > > > references_;
+ GcAllocator<std::pair<const byte*, std::vector<mirror::Object**> > > > references_;
};
// Card caching implementation. Keeps track of which cards we cleared and only this information.
diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc
index 63b24ff..52c02f7 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -62,9 +62,11 @@
CHECK(heap_begin != NULL);
// Round up since heap_capacity is not necessarily a multiple of kAlignment * kBitsPerWord.
size_t bitmap_size = OffsetToIndex(RoundUp(heap_capacity, kAlignment * kBitsPerWord)) * kWordSize;
- UniquePtr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), NULL, bitmap_size, PROT_READ | PROT_WRITE));
- if (mem_map.get() == NULL) {
- LOG(ERROR) << "Failed to allocate bitmap " << name;
+ std::string error_msg;
+ UniquePtr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), NULL, bitmap_size,
+ PROT_READ | PROT_WRITE, &error_msg));
+ if (UNLIKELY(mem_map.get() == nullptr)) {
+ LOG(ERROR) << "Failed to allocate bitmap " << name << ": " << error_msg;
return NULL;
}
return CreateFromMemMap(name, mem_map.release(), heap_begin, heap_capacity);
diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h
index 4cf8872..21709ad 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -212,7 +212,7 @@
public:
typedef std::set<
const mirror::Object*, std::less<const mirror::Object*>,
- GCAllocator<const mirror::Object*> > Objects;
+ GcAllocator<const mirror::Object*> > Objects;
bool IsEmpty() const {
return contained_.empty();
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index d26e28c..804c669 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -66,7 +66,7 @@
static constexpr size_t kMinConcurrentRemainingBytes = 128 * KB;
Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max_free,
- double target_utilization, size_t capacity, const std::string& original_image_file_name,
+ double target_utilization, size_t capacity, const std::string& image_file_name,
bool concurrent_gc, size_t parallel_gc_threads, size_t conc_gc_threads,
bool low_memory_mode, size_t long_pause_log_threshold, size_t long_gc_log_threshold,
bool ignore_max_footprint)
@@ -144,9 +144,8 @@
// Requested begin for the alloc space, to follow the mapped image and oat files
byte* requested_alloc_space_begin = NULL;
- std::string image_file_name(original_image_file_name);
if (!image_file_name.empty()) {
- space::ImageSpace* image_space = space::ImageSpace::Create(image_file_name);
+ space::ImageSpace* image_space = space::ImageSpace::Create(image_file_name.c_str());
CHECK(image_space != NULL) << "Failed to create space for " << image_file_name;
AddContinuousSpace(image_space);
// Oat files referenced by image files immediately follow them in memory, ensure alloc space
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index 468d1d2..8c13d79 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -183,11 +183,12 @@
growth_limit = RoundUp(growth_limit, kPageSize);
capacity = RoundUp(capacity, kPageSize);
+ std::string error_msg;
UniquePtr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), requested_begin, capacity,
- PROT_READ | PROT_WRITE));
+ PROT_READ | PROT_WRITE, &error_msg));
if (mem_map.get() == NULL) {
LOG(ERROR) << "Failed to allocate pages for alloc space (" << name << ") of size "
- << PrettySize(capacity);
+ << PrettySize(capacity) << ": " << error_msg;
return NULL;
}
@@ -307,7 +308,10 @@
VLOG(heap) << "Size " << GetMemMap()->Size();
VLOG(heap) << "GrowthLimit " << PrettySize(growth_limit);
VLOG(heap) << "Capacity " << PrettySize(capacity);
- UniquePtr<MemMap> mem_map(MemMap::MapAnonymous(alloc_space_name, End(), capacity, PROT_READ | PROT_WRITE));
+ std::string error_msg;
+ UniquePtr<MemMap> mem_map(MemMap::MapAnonymous(alloc_space_name, End(), capacity,
+ PROT_READ | PROT_WRITE, &error_msg));
+ CHECK(mem_map.get() != nullptr) << error_msg;
void* mspace = CreateMallocSpace(end_, starting_size, initial_size);
// Protect memory beyond the initial size.
byte* end = mem_map->Begin() + starting_size;
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 1cd33ee..fa28642 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -44,12 +44,13 @@
live_bitmap_.reset(live_bitmap);
}
-static bool GenerateImage(const std::string& image_file_name) {
+static bool GenerateImage(const std::string& image_file_name, std::string* error_msg) {
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);
if (boot_class_path.empty()) {
- LOG(FATAL) << "Failed to generate image because no boot class path specified";
+ *error_msg = "Failed to generate image because no boot class path specified";
+ return false;
}
std::vector<std::string> arg_vector;
@@ -112,41 +113,57 @@
return false;
} else {
if (pid == -1) {
- PLOG(ERROR) << "fork failed";
+ *error_msg = StringPrintf("Failed to generate image '%s' because fork failed: %s",
+ image_file_name.c_str(), strerror(errno));
+ return false;
}
// wait for dex2oat to finish
int status;
pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
if (got_pid != pid) {
- PLOG(ERROR) << "waitpid failed: wanted " << pid << ", got " << got_pid;
+ *error_msg = StringPrintf("Failed to generate image '%s' because waitpid failed: "
+ "wanted %d, got %d: %s",
+ image_file_name.c_str(), pid, got_pid, strerror(errno));
return false;
}
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- LOG(ERROR) << dex2oat << " failed: " << command_line;
+ *error_msg = StringPrintf("Failed to generate image '%s' because dex2oat failed: %s",
+ image_file_name.c_str(), command_line.c_str());
return false;
}
}
return true;
}
-ImageSpace* ImageSpace::Create(const std::string& original_image_file_name) {
- if (OS::FileExists(original_image_file_name.c_str())) {
+ImageSpace* ImageSpace::Create(const char* original_image_file_name) {
+ if (OS::FileExists(original_image_file_name)) {
// If the /system file exists, it should be up-to-date, don't try to generate
- return space::ImageSpace::Init(original_image_file_name, false);
+ std::string error_msg;
+ ImageSpace* space = ImageSpace::Init(original_image_file_name, false, &error_msg);
+ if (space == nullptr) {
+ LOG(FATAL) << "Failed to load image '" << original_image_file_name << "': " << error_msg;
+ }
+ return space;
}
// If the /system file didn't exist, we need to use one from the dalvik-cache.
// If the cache file exists, try to open, but if it fails, regenerate.
// If it does not exist, generate.
std::string image_file_name(GetDalvikCacheFilenameOrDie(original_image_file_name));
+ std::string error_msg;
if (OS::FileExists(image_file_name.c_str())) {
- space::ImageSpace* image_space = space::ImageSpace::Init(image_file_name, true);
- if (image_space != NULL) {
+ space::ImageSpace* image_space = ImageSpace::Init(image_file_name.c_str(), true, &error_msg);
+ if (image_space != nullptr) {
return image_space;
}
}
- CHECK(GenerateImage(image_file_name)) << "Failed to generate image: " << image_file_name;
- return space::ImageSpace::Init(image_file_name, true);
+ CHECK(GenerateImage(image_file_name, &error_msg))
+ << "Failed to generate image '" << image_file_name << "': " << error_msg;
+ ImageSpace* space = ImageSpace::Init(image_file_name.c_str(), true, &error_msg);
+ if (space == nullptr) {
+ LOG(FATAL) << "Failed to load image '" << original_image_file_name << "': " << error_msg;
+ }
+ return space;
}
void ImageSpace::VerifyImageAllocations() {
@@ -160,8 +177,9 @@
}
}
-ImageSpace* ImageSpace::Init(const std::string& image_file_name, bool validate_oat_file) {
- CHECK(!image_file_name.empty());
+ImageSpace* ImageSpace::Init(const char* image_file_name, bool validate_oat_file,
+ std::string* error_msg) {
+ CHECK(image_file_name != nullptr);
uint64_t start_time = 0;
if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
@@ -169,16 +187,16 @@
LOG(INFO) << "ImageSpace::Init entering image_file_name=" << image_file_name;
}
- UniquePtr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
+ UniquePtr<File> file(OS::OpenFileForReading(image_file_name));
if (file.get() == NULL) {
- LOG(ERROR) << "Failed to open " << image_file_name;
- return NULL;
+ *error_msg = StringPrintf("Failed to open '%s'", image_file_name);
+ return nullptr;
}
ImageHeader image_header;
bool success = file->ReadFully(&image_header, sizeof(image_header));
if (!success || !image_header.IsValid()) {
- LOG(ERROR) << "Invalid image header " << image_file_name;
- return NULL;
+ *error_msg = StringPrintf("Invalid image header in '%s'", image_file_name);
+ return nullptr;
}
// Note: The image header is part of the image due to mmap page alignment required of offset.
@@ -188,10 +206,12 @@
MAP_PRIVATE | MAP_FIXED,
file->Fd(),
0,
- false));
+ false,
+ image_file_name,
+ error_msg));
if (map.get() == NULL) {
- LOG(ERROR) << "Failed to map " << image_file_name;
- return NULL;
+ DCHECK(!error_msg->empty());
+ return nullptr;
}
CHECK_EQ(image_header.GetImageBegin(), map->Begin());
DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader)));
@@ -199,16 +219,24 @@
UniquePtr<MemMap> image_map(MemMap::MapFileAtAddress(nullptr, image_header.GetImageBitmapSize(),
PROT_READ, MAP_PRIVATE,
file->Fd(), image_header.GetBitmapOffset(),
- false));
- CHECK(image_map.get() != nullptr) << "failed to map image bitmap";
+ false,
+ image_file_name,
+ error_msg));
+ if (image_map.get() == nullptr) {
+ *error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str());
+ return nullptr;
+ }
size_t bitmap_index = bitmap_index_.fetch_add(1);
- std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u", image_file_name.c_str(),
+ std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u", image_file_name,
bitmap_index));
UniquePtr<accounting::SpaceBitmap> bitmap(
accounting::SpaceBitmap::CreateFromMemMap(bitmap_name, image_map.release(),
reinterpret_cast<byte*>(map->Begin()),
map->Size()));
- CHECK(bitmap.get() != nullptr) << "could not create " << bitmap_name;
+ if (bitmap.get() == nullptr) {
+ *error_msg = StringPrintf("Could not create bitmap '%s'", bitmap_name.c_str());
+ return nullptr;
+ }
Runtime* runtime = Runtime::Current();
mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
@@ -226,15 +254,15 @@
space->VerifyImageAllocations();
}
- space->oat_file_.reset(space->OpenOatFile());
- if (space->oat_file_.get() == NULL) {
- LOG(ERROR) << "Failed to open oat file for image: " << image_file_name;
- return NULL;
+ space->oat_file_.reset(space->OpenOatFile(error_msg));
+ if (space->oat_file_.get() == nullptr) {
+ DCHECK(!error_msg->empty());
+ return nullptr;
}
- if (validate_oat_file && !space->ValidateOatFile()) {
- LOG(WARNING) << "Failed to validate oat file for image: " << image_file_name;
- return NULL;
+ if (validate_oat_file && !space->ValidateOatFile(error_msg)) {
+ DCHECK(!error_msg->empty());
+ return nullptr;
}
if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
@@ -244,7 +272,7 @@
return space.release();
}
-OatFile* ImageSpace::OpenOatFile() const {
+OatFile* ImageSpace::OpenOatFile(std::string* error_msg) const {
const Runtime* runtime = Runtime::Current();
const ImageHeader& image_header = GetImageHeader();
// Grab location but don't use Object::AsString as we haven't yet initialized the roots to
@@ -255,45 +283,47 @@
oat_filename += runtime->GetHostPrefix();
oat_filename += oat_location->ToModifiedUtf8();
OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, image_header.GetOatDataBegin(),
- !Runtime::Current()->IsCompiler());
+ !Runtime::Current()->IsCompiler(), error_msg);
if (oat_file == NULL) {
- LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image.";
- return NULL;
+ *error_msg = StringPrintf("Failed to open oat file '%s' referenced from image %s: %s",
+ oat_filename.c_str(), GetName(), error_msg->c_str());
+ return nullptr;
}
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 file checksum " << std::hex << oat_checksum
- << " to expected oat checksum " << std::hex << image_oat_checksum
- << " in image";
- return NULL;
+ *error_msg = StringPrintf("Failed to match oat file checksum 0x%x to expected oat checksum 0x%x"
+ " in image %s", oat_checksum, image_oat_checksum, GetName());
+ return nullptr;
}
return oat_file;
}
-bool ImageSpace::ValidateOatFile() const {
+bool ImageSpace::ValidateOatFile(std::string* error_msg) const {
CHECK(oat_file_.get() != NULL);
for (const OatFile::OatDexFile* oat_dex_file : oat_file_->GetOatDexFiles()) {
const std::string& dex_file_location = oat_dex_file->GetDexFileLocation();
uint32_t dex_file_location_checksum;
- if (!DexFile::GetChecksum(dex_file_location.c_str(), &dex_file_location_checksum)) {
- LOG(WARNING) << "ValidateOatFile could not find checksum for " << dex_file_location;
+ if (!DexFile::GetChecksum(dex_file_location.c_str(), &dex_file_location_checksum, error_msg)) {
+ *error_msg = StringPrintf("Failed to get checksum of dex file '%s' referenced by image %s: "
+ "%s", dex_file_location.c_str(), GetName(), error_msg->c_str());
return false;
}
if (dex_file_location_checksum != oat_dex_file->GetDexFileLocationChecksum()) {
- LOG(WARNING) << "ValidateOatFile found checksum mismatch between oat file "
- << oat_file_->GetLocation() << " and dex file " << dex_file_location
- << " (" << oat_dex_file->GetDexFileLocationChecksum() << " != "
- << dex_file_location_checksum << ")";
+ *error_msg = StringPrintf("ValidateOatFile found checksum mismatch between oat file '%s' and "
+ "dex file '%s' (0x%x != 0x%x)",
+ oat_file_->GetLocation().c_str(), dex_file_location.c_str(),
+ oat_dex_file->GetDexFileLocationChecksum(),
+ dex_file_location_checksum);
return false;
}
}
return true;
}
-OatFile& ImageSpace::ReleaseOatFile() {
+OatFile* ImageSpace::ReleaseOatFile() {
CHECK(oat_file_.get() != NULL);
- return *oat_file_.release();
+ return oat_file_.release();
}
void ImageSpace::Dump(std::ostream& os) const {
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 381a98e..78a83c9 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -45,12 +45,11 @@
// creation of the alloc space. The ReleaseOatFile will later be
// used to transfer ownership of the OatFile to the ClassLinker when
// it is initialized.
- static ImageSpace* Create(const std::string& image)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static ImageSpace* Create(const char* image) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Releases the OatFile from the ImageSpace so it can be transfer to
// the caller, presumably the ClassLinker.
- OatFile& ReleaseOatFile()
+ OatFile* ReleaseOatFile()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void VerifyImageAllocations()
@@ -84,13 +83,13 @@
// image's OatFile is up-to-date relative to its DexFile
// inputs. Otherwise (for /data), validate the inputs and generate
// the OatFile in /data/dalvik-cache if necessary.
- static ImageSpace* Init(const std::string& image, bool validate_oat_file)
+ static ImageSpace* Init(const char* image, bool validate_oat_file, std::string* error_msg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- OatFile* OpenOatFile() const
+ OatFile* OpenOatFile(std::string* error_msg) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool ValidateOatFile() const
+ bool ValidateOatFile(std::string* error_msg) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
friend class Space;
diff --git a/runtime/gc/space/large_object_space.cc b/runtime/gc/space/large_object_space.cc
index c6d028e..1321b19 100644
--- a/runtime/gc/space/large_object_space.cc
+++ b/runtime/gc/space/large_object_space.cc
@@ -56,10 +56,13 @@
return new LargeObjectMapSpace(name);
}
-mirror::Object* LargeObjectMapSpace::Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated) {
+mirror::Object* LargeObjectMapSpace::Alloc(Thread* self, size_t num_bytes,
+ size_t* bytes_allocated) {
+ std::string error_msg;
MemMap* mem_map = MemMap::MapAnonymous("large object space allocation", NULL, num_bytes,
- PROT_READ | PROT_WRITE);
- if (mem_map == NULL) {
+ PROT_READ | PROT_WRITE, &error_msg);
+ if (UNLIKELY(mem_map == NULL)) {
+ LOG(WARNING) << "Large object allocation failed: " << error_msg;
return NULL;
}
MutexLock mu(self, lock_);
@@ -129,9 +132,10 @@
FreeListSpace* FreeListSpace::Create(const std::string& name, byte* requested_begin, size_t size) {
CHECK_EQ(size % kAlignment, 0U);
+ std::string error_msg;
MemMap* mem_map = MemMap::MapAnonymous(name.c_str(), requested_begin, size,
- PROT_READ | PROT_WRITE);
- CHECK(mem_map != NULL) << "Failed to allocate large object space mem map";
+ PROT_READ | PROT_WRITE, &error_msg);
+ CHECK(mem_map != NULL) << "Failed to allocate large object space mem map: " << error_msg;
return new FreeListSpace(name, mem_map, mem_map->Begin(), mem_map->End());
}
diff --git a/runtime/gc/space/large_object_space.h b/runtime/gc/space/large_object_space.h
index 3f2e848..ef889d4 100644
--- a/runtime/gc/space/large_object_space.h
+++ b/runtime/gc/space/large_object_space.h
@@ -96,9 +96,9 @@
// Used to ensure mutual exclusion when the allocation spaces data structures are being modified.
mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
std::vector<mirror::Object*,
- accounting::GCAllocator<mirror::Object*> > large_objects_ GUARDED_BY(lock_);
+ accounting::GcAllocator<mirror::Object*> > large_objects_ GUARDED_BY(lock_);
typedef SafeMap<mirror::Object*, MemMap*, std::less<mirror::Object*>,
- accounting::GCAllocator<std::pair<const mirror::Object*, MemMap*> > > MemMaps;
+ accounting::GcAllocator<std::pair<const mirror::Object*, MemMap*> > > MemMaps;
MemMaps mem_maps_ GUARDED_BY(lock_);
};
@@ -217,7 +217,7 @@
AllocationHeader* GetAllocationHeader(const mirror::Object* obj);
typedef std::set<AllocationHeader*, AllocationHeader::SortByPrevFree,
- accounting::GCAllocator<AllocationHeader*> > FreeBlocks;
+ accounting::GcAllocator<AllocationHeader*> > FreeBlocks;
byte* const begin_;
byte* const end_;