Compare checksum in oat files adjacent to jar/apk to support oat in system image
Change-Id: I45554c9fa5c369a0f47830623b6dbe7f9c691a08
diff --git a/Android.mk b/Android.mk
index 9c422b9..14a7679 100644
--- a/Android.mk
+++ b/Android.mk
@@ -233,7 +233,11 @@
# $(1): input jar or apk target location
define declare-oat-target-target
+ifneq (,$(filter $(1),$(addprefix system/app/,$(addsuffix .apk,$(PRODUCT_DEX_PREOPT_PACKAGES_IN_DATA)))))
OUT_OAT_FILE := $(call art-cache-out,$(1).oat)
+else
+OUT_OAT_FILE := $(PRODUCT_OUT)/$(1).oat
+endif
ifeq ($(ONE_SHOT_MAKEFILE),)
.PHONY: oat-target-$(1)
@@ -254,7 +258,7 @@
$(foreach file,\
$(filter-out\
- $(TARGET_BOOT_DEX),\
+ $(addprefix $(TARGET_OUT_JAVA_LIBRARIES)/,$(addsuffix .jar,$(TARGET_BOOT_JARS))),\
$(wildcard $(TARGET_OUT_APPS)/*.apk) $(wildcard $(TARGET_OUT_JAVA_LIBRARIES)/*.jar)),\
$(eval $(call declare-oat-target-target,$(subst $(PRODUCT_OUT)/,,$(file)))))
diff --git a/src/class_linker.cc b/src/class_linker.cc
index f891913..b18b31f 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -741,6 +741,40 @@
return oat_dex_file->OpenDexFile();
}
+const DexFile* ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file,
+ const std::string& dex_location,
+ uint32_t dex_location_checksum) {
+ Runtime* runtime = Runtime::Current();
+ const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
+ uint32_t image_checksum = image_header.GetOatChecksum();
+ bool image_check = (oat_file->GetOatHeader().GetImageFileLocationChecksum() == image_checksum);
+
+ const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
+ CHECK(oat_dex_file != NULL) << oat_file->GetLocation() << " " << dex_location;
+ bool dex_check = (dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum());
+
+ if (image_check && dex_check) {
+ RegisterOatFileLocked(*oat_file);
+ return oat_file->GetOatDexFile(dex_location)->OpenDexFile();
+ }
+
+ if (!image_check) {
+ std::string image_file(image_header.GetImageRoot(
+ ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8());
+ LOG(WARNING) << ".oat file " << oat_file->GetLocation()
+ << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
+ << ") mismatch with " << image_file
+ << " (" << std::hex << image_checksum << ")";
+ }
+ if (!dex_check) {
+ LOG(WARNING) << ".oat file " << oat_file->GetLocation()
+ << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
+ << ") mismatch with " << dex_location
+ << " (" << std::hex << dex_location_checksum << ")";
+ }
+ return NULL;
+}
+
const DexFile* ClassLinker::FindDexFileInOatFileFromDexLocation(const std::string& dex_location) {
MutexLock mu(dex_lock_);
@@ -749,14 +783,26 @@
return open_oat_file->GetOatDexFile(dex_location)->OpenDexFile();
}
- // Look for an existing file next to dex, assuming its up-to-date if found
+ // Look for an existing file next to dex. for example, for
+ // /foo/bar/baz.jar, look for /foo/bar/baz.jar.oat.
std::string oat_filename(OatFile::DexFilenameToOatFilename(dex_location));
const OatFile* oat_file = FindOatFileFromOatLocation(oat_filename);
if (oat_file != NULL) {
- const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
- CHECK(oat_dex_file != NULL) << oat_filename << " " << dex_location;
- RegisterOatFileLocked(*oat_file);
- return oat_dex_file->OpenDexFile();
+ uint32_t dex_location_checksum;
+ if (!DexFile::GetChecksum(dex_location, dex_location_checksum)) {
+ // If no classes.dex found in dex_location, it has been stripped, assume oat is up-to-date.
+ // This is the common case in user builds for jar's and apk's in the /system directory.
+ const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
+ CHECK(oat_dex_file != NULL) << oat_filename << " " << dex_location;
+ RegisterOatFileLocked(*oat_file);
+ return oat_dex_file->OpenDexFile();
+ }
+ const DexFile* dex_file = VerifyOatFileChecksums(oat_file,
+ dex_location,
+ dex_location_checksum);
+ if (dex_file != NULL) {
+ return dex_file;
+ }
}
// Look for an existing file in the art-cache, validating the result if found
// not found in /foo/bar/baz.oat? try /data/art-cache/foo@bar@baz.oat
@@ -768,33 +814,11 @@
LOG(WARNING) << "Failed to compute checksum: " << dex_location;
return NULL;
}
-
- Runtime* runtime = Runtime::Current();
- const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
- uint32_t image_checksum = image_header.GetOatChecksum();
- bool image_check = (oat_file->GetOatHeader().GetImageFileLocationChecksum() == image_checksum);
-
- const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
- CHECK(oat_dex_file != NULL) << oat_filename << " " << dex_location;
- bool dex_check = (dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum());
-
- if (image_check && dex_check) {
- RegisterOatFileLocked(*oat_file);
- return oat_file->GetOatDexFile(dex_location)->OpenDexFile();
- }
- if (!image_check) {
- std::string image_file(image_header.GetImageRoot(
- ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8());
- LOG(WARNING) << ".oat file " << oat_file->GetLocation()
- << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
- << ") mismatch with " << image_file
- << " (" << std::hex << image_checksum << ")--- regenerating";
- }
- if (!dex_check) {
- LOG(WARNING) << ".oat file " << oat_file->GetLocation()
- << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
- << ") mismatch with " << dex_location
- << " (" << std::hex << dex_location_checksum << ")--- regenerating";
+ const DexFile* dex_file = VerifyOatFileChecksums(oat_file,
+ dex_location,
+ dex_location_checksum);
+ if (dex_file != NULL) {
+ return dex_file;
}
if (TEMP_FAILURE_RETRY(unlink(oat_file->GetLocation().c_str())) != 0) {
PLOG(FATAL) << "Failed to remove obsolete .oat file " << oat_file->GetLocation();
diff --git a/src/class_linker.h b/src/class_linker.h
index 293e3ab..01c1051 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -404,6 +404,10 @@
const OatFile* FindOpenedOatFileForDexFile(const DexFile& dex_file);
const OatFile* FindOpenedOatFileFromDexLocation(const std::string& dex_location);
const OatFile* FindOpenedOatFileFromOatLocation(const std::string& oat_location);
+ const DexFile* VerifyOatFileChecksums(const OatFile* oat_file,
+ const std::string& dex_location,
+ uint32_t dex_location_checksum)
+ EXCLUSIVE_LOCKS_REQUIRED(dex_lock_);
Method* CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class);
Method* CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype);