diff options
author | Richard Uhler <ruhler@google.com> | 2015-06-25 15:21:12 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-06-25 15:21:13 +0000 |
commit | 9ae03f09f33c64b6589e85faeac4142b80531b10 (patch) | |
tree | 1269e5863e94ea0f86c2c7aa05a282f1782c2ed8 /runtime | |
parent | 92067896c6583d59171dbee9c720a316d63be177 (diff) | |
parent | cb44b11a926696e34b3dc44288e762b4303cc128 (diff) | |
download | art-9ae03f09f33c64b6589e85faeac4142b80531b10.zip art-9ae03f09f33c64b6589e85faeac4142b80531b10.tar.gz art-9ae03f09f33c64b6589e85faeac4142b80531b10.tar.bz2 |
Merge "Do not try to compile resource-only dex files." into mnc-dev
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/class_linker.cc | 15 | ||||
-rw-r--r-- | runtime/oat_file_assistant.cc | 28 | ||||
-rw-r--r-- | runtime/oat_file_assistant.h | 15 | ||||
-rw-r--r-- | runtime/oat_file_assistant_test.cc | 95 |
4 files changed, 109 insertions, 44 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 5240447..9ca6492 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -987,13 +987,18 @@ std::vector<std::unique_ptr<const DexFile>> ClassLinker::OpenDexFilesFromOat( // Fall back to running out of the original dex file if we couldn't load any // dex_files from the oat file. if (dex_files.empty()) { - if (Runtime::Current()->IsDexFileFallbackEnabled()) { - if (!DexFile::Open(dex_location, dex_location, &error_msg, &dex_files)) { - LOG(WARNING) << error_msg; - error_msgs->push_back("Failed to open dex files from " + std::string(dex_location)); + if (oat_file_assistant.HasOriginalDexFiles()) { + if (Runtime::Current()->IsDexFileFallbackEnabled()) { + if (!DexFile::Open(dex_location, dex_location, &error_msg, &dex_files)) { + LOG(WARNING) << error_msg; + error_msgs->push_back("Failed to open dex files from " + std::string(dex_location)); + } + } else { + error_msgs->push_back("Fallback mode disabled, skipping dex files."); } } else { - error_msgs->push_back("Fallback mode disabled, skipping dex files."); + error_msgs->push_back("No original dex files found for dex location " + + std::string(dex_location)); } } return dex_files; diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 094d8b7..b28adf9 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -151,7 +151,7 @@ OatFileAssistant::DexOptNeeded OatFileAssistant::GetDexOptNeeded() { return kSelfPatchOatNeeded; } - return kDex2OatNeeded; + return HasOriginalDexFiles() ? kDex2OatNeeded : kNoDexOptNeeded; } bool OatFileAssistant::MakeUpToDate(std::string* error_msg) { @@ -241,6 +241,14 @@ std::vector<std::unique_ptr<const DexFile>> OatFileAssistant::LoadDexFiles( return dex_files; } +bool OatFileAssistant::HasOriginalDexFiles() { + // Ensure GetRequiredDexChecksum has been run so that + // has_original_dex_files_ is initialized. We don't care about the result of + // GetRequiredDexChecksum. + GetRequiredDexChecksum(); + return has_original_dex_files_; +} + const std::string* OatFileAssistant::OdexFileName() { if (!cached_odex_file_name_attempted_) { CHECK(dex_location_ != nullptr) << "OatFileAssistant: null dex location"; @@ -817,17 +825,19 @@ std::string OatFileAssistant::ImageLocation() { } const uint32_t* OatFileAssistant::GetRequiredDexChecksum() { - if (!required_dex_checksum_attempted) { - required_dex_checksum_attempted = true; - required_dex_checksum_found = false; + if (!required_dex_checksum_attempted_) { + required_dex_checksum_attempted_ = true; + required_dex_checksum_found_ = false; std::string error_msg; CHECK(dex_location_ != nullptr) << "OatFileAssistant provided no dex location"; - if (DexFile::GetChecksum(dex_location_, &cached_required_dex_checksum, &error_msg)) { - required_dex_checksum_found = true; + if (DexFile::GetChecksum(dex_location_, &cached_required_dex_checksum_, &error_msg)) { + required_dex_checksum_found_ = true; + has_original_dex_files_ = true; } else { // This can happen if the original dex file has been stripped from the // apk. VLOG(oat) << "OatFileAssistant: " << error_msg; + has_original_dex_files_ = false; // Get the checksum from the odex if we can. const OatFile* odex_file = GetOdexFile(); @@ -835,13 +845,13 @@ const uint32_t* OatFileAssistant::GetRequiredDexChecksum() { const OatFile::OatDexFile* odex_dex_file = odex_file->GetOatDexFile( dex_location_, nullptr, false); if (odex_dex_file != nullptr) { - cached_required_dex_checksum = odex_dex_file->GetDexFileLocationChecksum(); - required_dex_checksum_found = true; + cached_required_dex_checksum_ = odex_dex_file->GetDexFileLocationChecksum(); + required_dex_checksum_found_ = true; } } } } - return required_dex_checksum_found ? &cached_required_dex_checksum : nullptr; + return required_dex_checksum_found_ ? &cached_required_dex_checksum_ : nullptr; } const OatFile* OatFileAssistant::GetOdexFile() { diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h index 4c0b0e2..7216fc7 100644 --- a/runtime/oat_file_assistant.h +++ b/runtime/oat_file_assistant.h @@ -174,6 +174,12 @@ class OatFileAssistant { static std::vector<std::unique_ptr<const DexFile>> LoadDexFiles( const OatFile& oat_file, const char* dex_location); + // Returns true if there are dex files in the original dex location that can + // be compiled with dex2oat for this dex location. + // Returns false if there is no original dex file, or if the original dex + // file is an apk/zip without a classes.dex entry. + bool HasOriginalDexFiles(); + // If the dex file has been installed with a compiled oat file alongside // it, the compiled oat file will have the extension .odex, and is referred // to as the odex file. It is called odex for legacy reasons; the file is @@ -312,6 +318,8 @@ class OatFileAssistant { // Returns dex_checksum if a required checksum was located. Returns // null if the required checksum was not found. // The caller shouldn't clean up or free the returned pointer. + // This sets the has_original_dex_files_ field to true if a checksum was + // found for the dex_location_ dex file. const uint32_t* GetRequiredDexChecksum(); // Returns the loaded odex file. @@ -374,9 +382,10 @@ class OatFileAssistant { // Cached value of the required dex checksum. // This should be accessed only by the GetRequiredDexChecksum() method. - uint32_t cached_required_dex_checksum; - bool required_dex_checksum_attempted = false; - bool required_dex_checksum_found; + uint32_t cached_required_dex_checksum_; + bool required_dex_checksum_attempted_ = false; + bool required_dex_checksum_found_; + bool has_original_dex_files_; // Cached value of the odex file name. // This should be accessed only by the OdexFileName() method. diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index d8e3797..570c59c 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -309,16 +309,24 @@ TEST_F(OatFileAssistantTest, DexNoOat) { EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OatFileStatus()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); } // Case: We have no DEX file and no OAT file. -// Expect: Status is kDex2OatNeeded. Loading should fail, but not crash. +// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash. TEST_F(OatFileAssistantTest, NoDexNoOat) { std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar"; OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); - EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); + EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); + EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); + + // Trying to make the oat file up to date should not fail or crash. + std::string error_msg; + EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)); + + // Trying to get the best oat file should fail, but not crash. std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); EXPECT_EQ(nullptr, oat_file.get()); } @@ -342,6 +350,7 @@ TEST_F(OatFileAssistantTest, OatUpToDate) { EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); } // Case: We have a MultiDEX file and up-to-date OAT file for it. @@ -353,6 +362,7 @@ TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) { OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); // Verify we can load both dex files. std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); @@ -378,6 +388,7 @@ TEST_F(OatFileAssistantTest, MultiDexSecondaryOutOfDate) { OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); } // Case: We have a MultiDEX file and up-to-date OAT file for it with relative @@ -432,6 +443,7 @@ TEST_F(OatFileAssistantTest, OatOutOfDate) { EXPECT_TRUE(oat_file_assistant.OatFileExists()); EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); } // Case: We have a DEX file and an ODEX file, but no OAT file. @@ -457,6 +469,7 @@ TEST_F(OatFileAssistantTest, DexOdexNoOat) { EXPECT_FALSE(oat_file_assistant.OatFileExists()); EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); } // Case: We have a stripped DEX file and an ODEX file, but no OAT file. @@ -484,6 +497,7 @@ TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) { EXPECT_FALSE(oat_file_assistant.OatFileExists()); EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); // Make the oat file up to date. std::string error_msg; @@ -498,6 +512,7 @@ TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) { EXPECT_TRUE(oat_file_assistant.OatFileExists()); EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); // Verify we can load the dex files from it. std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); @@ -538,6 +553,7 @@ TEST_F(OatFileAssistantTest, StrippedDexOdexOat) { EXPECT_TRUE(oat_file_assistant.OatFileExists()); EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); // Make the oat file up to date. std::string error_msg; @@ -554,6 +570,7 @@ TEST_F(OatFileAssistantTest, StrippedDexOdexOat) { EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); // Verify we can load the dex files from it. std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); @@ -564,6 +581,45 @@ TEST_F(OatFileAssistantTest, StrippedDexOdexOat) { EXPECT_EQ(1u, dex_files.size()); } +// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no +// OAT file. Expect: The status is kNoDexOptNeeded. +TEST_F(OatFileAssistantTest, ResourceOnlyDex) { + std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar"; + + Copy(GetStrippedDexSrc1(), dex_location); + + // Verify the status. + OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); + + EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); + + EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); + EXPECT_FALSE(oat_file_assistant.OdexFileExists()); + EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); + EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); + EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); + EXPECT_FALSE(oat_file_assistant.OatFileExists()); + EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); + EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); + + // Make the oat file up to date. This should have no effect. + std::string error_msg; + EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; + + EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); + + EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); + EXPECT_FALSE(oat_file_assistant.OdexFileExists()); + EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); + EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); + EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); + EXPECT_FALSE(oat_file_assistant.OatFileExists()); + EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); + EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); +} + // Case: We have a DEX file, no ODEX file and an OAT file that needs // relocation. // Expect: The status is kSelfPatchOatNeeded. @@ -589,6 +645,7 @@ TEST_F(OatFileAssistantTest, SelfRelocation) { EXPECT_TRUE(oat_file_assistant.OatFileNeedsRelocation()); EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); // Make the oat file up to date. std::string error_msg; @@ -605,6 +662,7 @@ TEST_F(OatFileAssistantTest, SelfRelocation) { EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); ASSERT_TRUE(oat_file.get() != nullptr); @@ -643,6 +701,7 @@ TEST_F(OatFileAssistantTest, OdexOatOverlap) { EXPECT_TRUE(oat_file_assistant.OatFileExists()); EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); // Things aren't relocated, so it should fall back to interpreted. std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); @@ -688,6 +747,7 @@ TEST_F(OatFileAssistantTest, DexPicOdexNoOat) { EXPECT_FALSE(oat_file_assistant.OatFileExists()); EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); } // Case: We have a DEX file and up-to-date OAT file for it. @@ -756,27 +816,6 @@ TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) { EXPECT_FALSE(ofm.OatFileExists()); } -// Case: Non-existent Dex location. -// Expect: The dex code is out of date, and trying to update it fails. -TEST_F(OatFileAssistantTest, NonExsistentDexLocation) { - std::string dex_location = GetScratchDir() + "/BadDexLocation.jar"; - - OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); - - EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); - EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); - EXPECT_FALSE(oat_file_assistant.OdexFileExists()); - EXPECT_FALSE(oat_file_assistant.OatFileExists()); - EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); - EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); - EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); - EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); - - std::string error_msg; - EXPECT_FALSE(oat_file_assistant.MakeUpToDate(&error_msg)); - EXPECT_FALSE(error_msg.empty()); -} - // Turn an absolute path into a path relative to the current working // directory. static std::string MakePathRelative(std::string target) { @@ -833,24 +872,26 @@ TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) { } // Case: Very short, non-existent Dex location. -// Expect: Dex code is out of date, and trying to update it fails. +// Expect: kNoDexOptNeeded. TEST_F(OatFileAssistantTest, ShortDexLocation) { std::string dex_location = "/xx"; OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); - EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); + EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); EXPECT_FALSE(oat_file_assistant.OdexFileExists()); EXPECT_FALSE(oat_file_assistant.OatFileExists()); EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); + EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); + // Trying to make it up to date should have no effect. std::string error_msg; - EXPECT_FALSE(oat_file_assistant.MakeUpToDate(&error_msg)); - EXPECT_FALSE(error_msg.empty()); + EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)); + EXPECT_TRUE(error_msg.empty()); } // Case: Non-standard extension for dex file. |