diff options
Diffstat (limited to 'runtime/native/dalvik_system_DexFile.cc')
-rw-r--r-- | runtime/native/dalvik_system_DexFile.cc | 140 |
1 files changed, 77 insertions, 63 deletions
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index 4e17b79..af09a1c 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -89,34 +89,32 @@ static jint DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceNam if (sourceName.c_str() == NULL) { return 0; } - std::string dex_location(sourceName.c_str()); NullableScopedUtfChars outputName(env, javaOutputName); if (env->ExceptionCheck()) { return 0; } - ScopedObjectAccess soa(env); + uint32_t dex_location_checksum; - if (!DexFile::GetChecksum(dex_location, &dex_location_checksum)) { - LOG(WARNING) << "Failed to compute checksum: " << dex_location; - ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow(); - soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/io/IOException;", - "Unable to get checksum of dex file: %s", dex_location.c_str()); + std::string error_msg; + if (!DexFile::GetChecksum(sourceName.c_str(), &dex_location_checksum, &error_msg)) { + ScopedObjectAccess soa(env); + DCHECK(!error_msg.empty()); + ThrowIOException("%s", error_msg.c_str()); return 0; } ClassLinker* linker = Runtime::Current()->GetClassLinker(); const DexFile* dex_file; - if (outputName.c_str() == NULL) { - dex_file = linker->FindDexFileInOatFileFromDexLocation(dex_location, dex_location_checksum); + if (outputName.c_str() == nullptr) { + dex_file = linker->FindDexFileInOatFileFromDexLocation(sourceName.c_str(), + dex_location_checksum, &error_msg); } else { - std::string oat_location(outputName.c_str()); - dex_file = linker->FindOrCreateOatFileForDexLocation(dex_location, dex_location_checksum, oat_location); + dex_file = linker->FindOrCreateOatFileForDexLocation(sourceName.c_str(), dex_location_checksum, + outputName.c_str(), &error_msg); } - if (dex_file == NULL) { - LOG(WARNING) << "Failed to open dex file: " << dex_location; - ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow(); - soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/io/IOException;", - "Unable to open dex file: %s", dex_location.c_str()); + if (dex_file == nullptr) { + ScopedObjectAccess soa(env); + ThrowIOException("%s", error_msg.c_str()); return 0; } return static_cast<jint>(reinterpret_cast<uintptr_t>(dex_file)); @@ -188,21 +186,17 @@ static jobjectArray DexFile_getClassNameList(JNIEnv* env, jclass, jint cookie) { } static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename) { - bool debug_logging = false; + const bool kVerboseLogging = false; // Spammy logging. + const bool kDebugLogging = true; // Logging useful for debugging. ScopedUtfChars filename(env, javaFilename); - if (filename.c_str() == NULL) { - LOG(ERROR) << "DexFile_isDexOptNeeded null filename"; - return JNI_TRUE; - } - if (!OS::FileExists(filename.c_str())) { + if ((filename.c_str() == nullptr) || !OS::FileExists(filename.c_str())) { LOG(ERROR) << "DexFile_isDexOptNeeded file '" << filename.c_str() << "' does not exist"; - ScopedObjectAccess soa(env); - ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow(); - soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/io/FileNotFoundException;", - "%s", filename.c_str()); - return JNI_TRUE; + ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException")); + const char* message = (filename.c_str() == nullptr) ? "<empty file name>" : filename.c_str(); + env->ThrowNew(fnfe.get(), message); + return JNI_FALSE; } // Always treat elements of the bootclasspath as up-to-date. The @@ -212,7 +206,7 @@ static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename const std::vector<const DexFile*>& boot_class_path = class_linker->GetBootClassPath(); for (size_t i = 0; i < boot_class_path.size(); i++) { if (boot_class_path[i]->GetLocation() == filename.c_str()) { - if (debug_logging) { + if (kVerboseLogging) { LOG(INFO) << "DexFile_isDexOptNeeded ignoring boot class path file: " << filename.c_str(); } return JNI_FALSE; @@ -221,26 +215,32 @@ static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename // Check if we have an odex file next to the dex file. std::string odex_filename(OatFile::DexFilenameToOdexFilename(filename.c_str())); - UniquePtr<const OatFile> oat_file(OatFile::Open(odex_filename, odex_filename, NULL, false)); - if (oat_file.get() != NULL) { - ScopedObjectAccess soa(env); - const art::OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(filename.c_str(), NULL); - if (oat_dex_file == NULL) { - if (debug_logging) { - LOG(INFO) << "DexFile_isDexOptNeeded GetOatDexFile failed"; - } - } else { + std::string error_msg; + UniquePtr<const OatFile> oat_file(OatFile::Open(odex_filename, odex_filename, NULL, false, + &error_msg)); + if (oat_file.get() == nullptr) { + if (kVerboseLogging) { + LOG(INFO) << "DexFile_isDexOptNeeded failed to open oat file '" << filename.c_str() + << "': " << error_msg; + } + error_msg.clear(); + } else { + const art::OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(filename.c_str(), NULL, + kDebugLogging); + if (oat_dex_file != nullptr) { uint32_t location_checksum; - // If we have no classes.dex checksum such as in a user build, assume up-to-date. - if (!DexFile::GetChecksum(filename.c_str(), &location_checksum)) { - if (debug_logging) { + // If its not possible to read the classes.dex assume up-to-date as we won't be able to + // compile it anyway. + if (!DexFile::GetChecksum(filename.c_str(), &location_checksum, &error_msg)) { + if (kVerboseLogging) { LOG(INFO) << "DexFile_isDexOptNeeded ignoring precompiled stripped file: " - << filename.c_str(); + << filename.c_str() << ": " << error_msg; } return JNI_FALSE; } - if (ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename.c_str(), location_checksum)) { - if (debug_logging) { + if (ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename.c_str(), location_checksum, + &error_msg)) { + if (kVerboseLogging) { LOG(INFO) << "DexFile_isDexOptNeeded precompiled file " << odex_filename << " is up-to-date checksum compared to " << filename.c_str(); } @@ -251,10 +251,12 @@ static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename // Check if we have an oat file in the cache std::string cache_location(GetDalvikCacheFilenameOrDie(filename.c_str())); - oat_file.reset(OatFile::Open(cache_location, filename.c_str(), NULL, false)); - if (oat_file.get() == NULL) { - LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location - << " does not exist for " << filename.c_str(); + oat_file.reset(OatFile::Open(cache_location, filename.c_str(), NULL, false, &error_msg)); + if (oat_file.get() == nullptr) { + if (kDebugLogging) { + LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location + << " does not exist for " << filename.c_str() << ": " << error_msg; + } return JNI_TRUE; } @@ -262,41 +264,53 @@ static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename if (space->IsImageSpace()) { // TODO: Ensure this works with multiple image spaces. const ImageHeader& image_header = space->AsImageSpace()->GetImageHeader(); - if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != image_header.GetOatChecksum()) { - ScopedObjectAccess soa(env); - LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location - << " has out-of-date oat checksum compared to " - << image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8(); + if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != + image_header.GetOatChecksum()) { + if (kDebugLogging) { + ScopedObjectAccess soa(env); + LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location + << " has out-of-date oat checksum compared to " + << image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8(); + } return JNI_TRUE; } if (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin() != reinterpret_cast<uint32_t>(image_header.GetOatDataBegin())) { - ScopedObjectAccess soa(env); - LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location - << " has out-of-date oat begin compared to " - << image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8(); + if (kDebugLogging) { + ScopedObjectAccess soa(env); + LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location + << " has out-of-date oat begin compared to " + << image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8(); + } return JNI_TRUE; } } } - ScopedObjectAccess soa(env); uint32_t location_checksum; - if (!DexFile::GetChecksum(filename.c_str(), &location_checksum)) { - LOG(ERROR) << "DexFile_isDexOptNeeded failed to compute checksum of " << filename.c_str(); + if (!DexFile::GetChecksum(filename.c_str(), &location_checksum, &error_msg)) { + if (kDebugLogging) { + LOG(ERROR) << "DexFile_isDexOptNeeded failed to compute checksum of " << filename.c_str() + << " (error " << error_msg << ")"; + } return JNI_TRUE; } - if (!ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename.c_str(), location_checksum)) { - LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location - << " has out-of-date checksum compared to " << filename.c_str(); + if (!ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename.c_str(), location_checksum, + &error_msg)) { + if (kDebugLogging) { + LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location + << " has out-of-date checksum compared to " << filename.c_str() + << " (error " << error_msg << ")"; + } return JNI_TRUE; } - if (debug_logging) { + if (kVerboseLogging) { LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location << " is up-to-date for " << filename.c_str(); } + CHECK(error_msg.empty()) << error_msg; return JNI_FALSE; } |