ART: Account for multidex location strings in VMClassLoader
To look up resources, look in the unadorned location.
Bug: 16530747
(cherry picked from commit cb8f9e8a2941971c049b26745ea713c859342d9b)
Change-Id: I5dce30c5e3c9f38fb5436c43a3f4a51fe4062c24
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 04f1cc1..d64a030 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -382,6 +382,20 @@
return location_;
}
+ // For normal dex files, location and base location coincide. If a dex file is part of a multidex
+ // archive, the base location is the name of the originating jar/apk, stripped of any internal
+ // classes*.dex path.
+ const std::string GetBaseLocation() const {
+ if (IsMultiDexLocation(location_.c_str())) {
+ std::pair<const char*, const char*> pair = SplitMultiDexLocation(location_.c_str());
+ std::string res(pair.first);
+ delete[] pair.first;
+ return res;
+ } else {
+ return location_;
+ }
+ }
+
// For DexFiles directly from .dex files, this is the checksum from the DexFile::Header.
// For DexFiles opened from a zip files, this will be the ZipEntry CRC32 of classes.dex.
uint32_t GetLocationChecksum() const {
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index f2b8a03..fefddae 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -62,25 +62,28 @@
*/
static jstring VMClassLoader_getBootClassPathResource(JNIEnv* env, jclass, jstring javaName, jint index) {
ScopedUtfChars name(env, javaName);
- if (name.c_str() == NULL) {
- return NULL;
+ if (name.c_str() == nullptr) {
+ return nullptr;
}
const std::vector<const DexFile*>& path = Runtime::Current()->GetClassLinker()->GetBootClassPath();
if (index < 0 || size_t(index) >= path.size()) {
- return NULL;
+ return nullptr;
}
const DexFile* dex_file = path[index];
- const std::string& location(dex_file->GetLocation());
+
+ // For multidex locations, e.g., x.jar:classes2.dex, we want to look into x.jar.
+ const std::string& location(dex_file->GetBaseLocation());
+
std::string error_msg;
std::unique_ptr<ZipArchive> zip_archive(ZipArchive::Open(location.c_str(), &error_msg));
if (zip_archive.get() == nullptr) {
LOG(WARNING) << "Failed to open zip archive '" << location << "': " << error_msg;
- return NULL;
+ return nullptr;
}
std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(name.c_str(), &error_msg));
- if (zip_entry.get() == NULL) {
- return NULL;
+ if (zip_entry.get() == nullptr) {
+ return nullptr;
}
std::string url;