summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorRichard Uhler <ruhler@google.com>2015-06-25 15:21:12 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-06-25 15:21:13 +0000
commit9ae03f09f33c64b6589e85faeac4142b80531b10 (patch)
tree1269e5863e94ea0f86c2c7aa05a282f1782c2ed8 /runtime
parent92067896c6583d59171dbee9c720a316d63be177 (diff)
parentcb44b11a926696e34b3dc44288e762b4303cc128 (diff)
downloadart-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.cc15
-rw-r--r--runtime/oat_file_assistant.cc28
-rw-r--r--runtime/oat_file_assistant.h15
-rw-r--r--runtime/oat_file_assistant_test.cc95
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.