diff options
| author | 2014-09-29 11:22:54 -0700 | |
|---|---|---|
| committer | 2014-09-30 21:49:43 -0700 | |
| commit | 31d8f5295c24730a57cb36cbc41197f0b7e8397c (patch) | |
| tree | e37953f590f924e06b9905f922407559a3661cb6 | |
| parent | 8283e079a209e81caafd123a12a525922368fd34 (diff) | |
Add VMRuntime.isBootClassPathOnDisk
Bug: 17679443
(cherry picked from commit 95a935415d44903b28326424beb4db5c013ef089)
Change-Id: Iba40291dead3f0b6715903c986370fd0cf1e41e1
| -rw-r--r-- | runtime/class_linker.cc | 2 | ||||
| -rw-r--r-- | runtime/gc/space/image_space.cc | 68 | ||||
| -rw-r--r-- | runtime/gc/space/image_space.h | 9 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_VMRuntime.cc | 33 | ||||
| -rw-r--r-- | runtime/runtime.cc | 1 | ||||
| -rw-r--r-- | runtime/runtime.h | 5 | ||||
| -rw-r--r-- | test/118-noimage-dex2oat/expected.txt | 6 | ||||
| -rw-r--r-- | test/118-noimage-dex2oat/src/Main.java | 36 |
8 files changed, 127 insertions, 33 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 2cf3820ace..6ed27bb945 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1179,7 +1179,7 @@ bool ClassLinker::VerifyOatChecksums(const OatFile* oat_file, uint32_t image_oat_checksum = 0; uintptr_t image_oat_data_begin = 0; int32_t image_patch_delta = 0; - if (instruction_set == Runtime::Current()->GetInstructionSet()) { + if (instruction_set == runtime->GetInstructionSet()) { const ImageHeader& image_header = image_space->GetImageHeader(); image_oat_checksum = image_header.GetOatChecksum(); image_oat_data_begin = reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()); diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 353d00c3dd..59630fe71c 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -149,7 +149,8 @@ static bool GenerateImage(const std::string& image_filename, InstructionSet imag arg_vector.push_back(oat_file_option_string); Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&arg_vector); - CHECK_EQ(image_isa, kRuntimeISA) << "We should always be generating an image for the current isa."; + CHECK_EQ(image_isa, kRuntimeISA) + << "We should always be generating an image for the current isa."; int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA, ART_BASE_ADDRESS_MAX_DELTA); @@ -270,10 +271,10 @@ static bool RelocateImage(const char* image_location, const char* dest_filename, return Exec(argv, error_msg); } -static ImageHeader* ReadSpecificImageHeaderOrDie(const char* filename) { +static ImageHeader* ReadSpecificImageHeader(const char* filename, std::string* error_msg) { std::unique_ptr<ImageHeader> hdr(new ImageHeader); if (!ReadSpecificImageHeader(filename, hdr.get())) { - LOG(FATAL) << "Unable to read image header for " << filename; + *error_msg = StringPrintf("Unable to read image header for %s", filename); return nullptr; } return hdr.release(); @@ -281,6 +282,17 @@ static ImageHeader* ReadSpecificImageHeaderOrDie(const char* filename) { ImageHeader* ImageSpace::ReadImageHeaderOrDie(const char* image_location, const InstructionSet image_isa) { + std::string error_msg; + ImageHeader* image_header = ReadImageHeader(image_location, image_isa, &error_msg); + if (image_header == nullptr) { + LOG(FATAL) << error_msg; + } + return image_header; +} + +ImageHeader* ImageSpace::ReadImageHeader(const char* image_location, + const InstructionSet image_isa, + std::string* error_msg) { std::string system_filename; bool has_system = false; std::string cache_filename; @@ -294,33 +306,37 @@ ImageHeader* ImageSpace::ReadImageHeaderOrDie(const char* image_location, std::unique_ptr<ImageHeader> sys_hdr(new ImageHeader); std::unique_ptr<ImageHeader> cache_hdr(new ImageHeader); if (!ReadSpecificImageHeader(system_filename.c_str(), sys_hdr.get())) { - LOG(FATAL) << "Unable to read image header for " << image_location << " at " - << system_filename; + *error_msg = StringPrintf("Unable to read image header for %s at %s", + image_location, system_filename.c_str()); return nullptr; } if (!ReadSpecificImageHeader(cache_filename.c_str(), cache_hdr.get())) { - LOG(FATAL) << "Unable to read image header for " << image_location << " at " - << cache_filename; + *error_msg = StringPrintf("Unable to read image header for %s at %s", + image_location, cache_filename.c_str()); return nullptr; } if (sys_hdr->GetOatChecksum() != cache_hdr->GetOatChecksum()) { - LOG(FATAL) << "Unable to find a relocated version of image file " << image_location; + *error_msg = StringPrintf("Unable to find a relocated version of image file %s", + image_location); return nullptr; } return cache_hdr.release(); } else if (!has_cache) { - LOG(FATAL) << "Unable to find a relocated version of image file " << image_location; + *error_msg = StringPrintf("Unable to find a relocated version of image file %s", + image_location); return nullptr; } else if (!has_system && has_cache) { // This can probably just use the cache one. - return ReadSpecificImageHeaderOrDie(cache_filename.c_str()); + return ReadSpecificImageHeader(cache_filename.c_str(), error_msg); } } else { // We don't want to relocate, Just pick the appropriate one if we have it and return. if (has_system && has_cache) { // We want the cache if the checksum matches, otherwise the system. - std::unique_ptr<ImageHeader> system(ReadSpecificImageHeaderOrDie(system_filename.c_str())); - std::unique_ptr<ImageHeader> cache(ReadSpecificImageHeaderOrDie(cache_filename.c_str())); + std::unique_ptr<ImageHeader> system(ReadSpecificImageHeader(system_filename.c_str(), + error_msg)); + std::unique_ptr<ImageHeader> cache(ReadSpecificImageHeader(cache_filename.c_str(), + error_msg)); if (system.get() == nullptr || (cache.get() != nullptr && cache->GetOatChecksum() == system->GetOatChecksum())) { return cache.release(); @@ -328,14 +344,14 @@ ImageHeader* ImageSpace::ReadImageHeaderOrDie(const char* image_location, return system.release(); } } else if (has_system) { - return ReadSpecificImageHeaderOrDie(system_filename.c_str()); + return ReadSpecificImageHeader(system_filename.c_str(), error_msg); } else if (has_cache) { - return ReadSpecificImageHeaderOrDie(cache_filename.c_str()); + return ReadSpecificImageHeader(cache_filename.c_str(), error_msg); } } } - LOG(FATAL) << "Unable to find image file for: " << image_location; + *error_msg = StringPrintf("Unable to find image file for %s", image_location); return nullptr; } @@ -563,12 +579,13 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat CHECK_EQ(image_header.GetImageBegin(), map->Begin()); DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader))); - std::unique_ptr<MemMap> image_map(MemMap::MapFileAtAddress(nullptr, image_header.GetImageBitmapSize(), - PROT_READ, MAP_PRIVATE, - file->Fd(), image_header.GetBitmapOffset(), - false, - image_filename, - error_msg)); + std::unique_ptr<MemMap> image_map( + MemMap::MapFileAtAddress(nullptr, image_header.GetImageBitmapSize(), + PROT_READ, MAP_PRIVATE, + file->Fd(), image_header.GetBitmapOffset(), + false, + image_filename, + error_msg)); if (image_map.get() == nullptr) { *error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str()); return nullptr; @@ -616,11 +633,14 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat runtime->SetDefaultImt(down_cast<mirror::ObjectArray<mirror::ArtMethod>*>(default_imt)); mirror::Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod); - runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kSaveAll); + runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), + Runtime::kSaveAll); callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsOnlySaveMethod); - runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kRefsOnly); + runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), + Runtime::kRefsOnly); callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod); - runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kRefsAndArgs); + runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), + Runtime::kRefsAndArgs); if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) { LOG(INFO) << "ImageSpace::Init exiting (" << PrettyDuration(NanoTime() - start_time) diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h index 2586ece4ab..d7f8057dc0 100644 --- a/runtime/gc/space/image_space.h +++ b/runtime/gc/space/image_space.h @@ -47,10 +47,17 @@ class ImageSpace : public MemMapSpace { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Reads the image header from the specified image location for the - // instruction set image_isa. + // instruction set image_isa or dies trying. static ImageHeader* ReadImageHeaderOrDie(const char* image_location, InstructionSet image_isa); + // Reads the image header from the specified image location for the + // instruction set image_isa. Returns nullptr on failure, with + // reason in error_msg. + static ImageHeader* ReadImageHeader(const char* image_location, + InstructionSet image_isa, + std::string* error_msg); + // Give access to the OatFile. const OatFile* GetOatFile() const; diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 64d4fe2715..23f46f41d9 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -16,6 +16,7 @@ #include <limits.h> +#include "ScopedUtfChars.h" #include "class_linker-inl.h" #include "common_throws.h" #include "debugger.h" @@ -24,6 +25,8 @@ #include "gc/allocator/dlmalloc.h" #include "gc/heap.h" #include "gc/space/dlmalloc_space.h" +#include "gc/space/image_space.h" +#include "instruction_set.h" #include "intern_table.h" #include "jni_internal.h" #include "mirror/art_method-inl.h" @@ -91,7 +94,8 @@ static jobject VMRuntime_newUnpaddedArray(JNIEnv* env, jobject, jclass javaEleme return nullptr; } Runtime* runtime = Runtime::Current(); - mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), &element_class); + mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), + &element_class); if (UNLIKELY(array_class == nullptr)) { return nullptr; } @@ -518,6 +522,28 @@ static void VMRuntime_registerAppInfo(JNIEnv* env, jclass, jstring pkgName, env->ReleaseStringUTFChars(pkgName, pkgNameChars); } +static jboolean VMRuntime_isBootClassPathOnDisk(JNIEnv* env, jclass, jstring java_instruction_set) { + ScopedUtfChars instruction_set(env, java_instruction_set); + if (instruction_set.c_str() == nullptr) { + return JNI_FALSE; + } + InstructionSet isa = GetInstructionSetFromString(instruction_set.c_str()); + if (isa == kNone) { + ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException")); + std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str())); + env->ThrowNew(iae.get(), message.c_str()); + return JNI_FALSE; + } + std::string error_msg; + std::unique_ptr<ImageHeader> image_header(gc::space::ImageSpace::ReadImageHeader( + Runtime::Current()->GetImageLocation().c_str(), isa, &error_msg)); + return image_header.get() != nullptr; +} + +static jstring VMRuntime_getCurrentInstructionSet(JNIEnv* env, jclass) { + return env->NewStringUTF(GetInstructionSetString(kRuntimeISA)); +} + static JNINativeMethod gMethods[] = { NATIVE_METHOD(VMRuntime, addressOf, "!(Ljava/lang/Object;)J"), NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"), @@ -543,7 +569,10 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(VMRuntime, is64Bit, "!()Z"), NATIVE_METHOD(VMRuntime, isCheckJniEnabled, "!()Z"), NATIVE_METHOD(VMRuntime, preloadDexCaches, "()V"), - NATIVE_METHOD(VMRuntime, registerAppInfo, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"), + NATIVE_METHOD(VMRuntime, registerAppInfo, + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"), + NATIVE_METHOD(VMRuntime, isBootClassPathOnDisk, "(Ljava/lang/String;)Z"), + NATIVE_METHOD(VMRuntime, getCurrentInstructionSet, "()Ljava/lang/String;"), }; void register_dalvik_system_VMRuntime(JNIEnv* env) { diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 49f8c63d75..48439b6000 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -678,6 +678,7 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) compiler_executable_ = options->compiler_executable_; compiler_options_ = options->compiler_options_; image_compiler_options_ = options->image_compiler_options_; + image_location_ = options->image_; max_spins_before_thin_lock_inflation_ = options->max_spins_before_thin_lock_inflation_; diff --git a/runtime/runtime.h b/runtime/runtime.h index 35e3a8896c..1a6c6e0c54 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -137,6 +137,10 @@ class Runtime { return image_compiler_options_; } + const std::string& GetImageLocation() const { + return image_location_; + } + const ProfilerOptions& GetProfilerOptions() const { return profiler_options_; } @@ -537,6 +541,7 @@ class Runtime { std::string patchoat_executable_; std::vector<std::string> compiler_options_; std::vector<std::string> image_compiler_options_; + std::string image_location_; std::string boot_class_path_string_; std::string class_path_string_; diff --git a/test/118-noimage-dex2oat/expected.txt b/test/118-noimage-dex2oat/expected.txt index 472a5f2c4d..6825fae41f 100644 --- a/test/118-noimage-dex2oat/expected.txt +++ b/test/118-noimage-dex2oat/expected.txt @@ -1,6 +1,6 @@ Run -Xnoimage-dex2oat -Has image is false, is image dex2oat enabled is false. +Has image is false, is image dex2oat enabled is false, is BOOTCLASSPATH on disk is false. Run -Ximage-dex2oat -Has image is true, is image dex2oat enabled is true. +Has image is true, is image dex2oat enabled is true, is BOOTCLASSPATH on disk is true. Run default -Has image is true, is image dex2oat enabled is true. +Has image is true, is image dex2oat enabled is true, is BOOTCLASSPATH on disk is true. diff --git a/test/118-noimage-dex2oat/src/Main.java b/test/118-noimage-dex2oat/src/Main.java index 11c736a7d6..c83b84de60 100644 --- a/test/118-noimage-dex2oat/src/Main.java +++ b/test/118-noimage-dex2oat/src/Main.java @@ -14,18 +14,28 @@ * limitations under the License. */ +import java.lang.reflect.Method; + public class Main { - public static void main(String[] args) { + public static void main(String[] args) throws Exception { boolean hasImage = hasImage(); + String instructionSet = VMRuntime.getCurrentInstructionSet(); + boolean isBootClassPathOnDisk = VMRuntime.isBootClassPathOnDisk(instructionSet); System.out.println( "Has image is " + hasImage + ", is image dex2oat enabled is " - + isImageDex2OatEnabled() + "."); + + isImageDex2OatEnabled() + ", is BOOTCLASSPATH on disk is " + + isBootClassPathOnDisk + "."); if (hasImage && !isImageDex2OatEnabled()) { throw new Error("Image with dex2oat disabled runs with an oat file"); } else if (!hasImage && isImageDex2OatEnabled()) { throw new Error("Image with dex2oat enabled runs without an oat file"); } + if (hasImage && !isBootClassPathOnDisk) { + throw new Error("Image with dex2oat disabled runs with an image file"); + } else if (!hasImage && isBootClassPathOnDisk) { + throw new Error("Image with dex2oat enabled runs without an image file"); + } } static { @@ -35,4 +45,26 @@ public class Main { private native static boolean hasImage(); private native static boolean isImageDex2OatEnabled(); + + private static class VMRuntime { + private static final Method getCurrentInstructionSetMethod; + private static final Method isBootClassPathOnDiskMethod; + static { + try { + Class c = Class.forName("dalvik.system.VMRuntime"); + getCurrentInstructionSetMethod = c.getDeclaredMethod("getCurrentInstructionSet"); + isBootClassPathOnDiskMethod = c.getDeclaredMethod("isBootClassPathOnDisk", + String.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String getCurrentInstructionSet() throws Exception { + return (String) getCurrentInstructionSetMethod.invoke(null); + } + public static boolean isBootClassPathOnDisk(String instructionSet) throws Exception { + return (boolean) isBootClassPathOnDiskMethod.invoke(null, instructionSet); + } + } } |