summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc63
1 files changed, 58 insertions, 5 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 6418c1a885..b4720c2dbc 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -92,12 +92,14 @@
#include "gc/space/image_space.h"
#include "gc/space/space-inl.h"
#include "gc_root-inl.h"
+#include "handle.h"
#include "handle_scope-inl.h"
#include "hidden_api.h"
#include "imt_conflict_table.h"
#include "imtable-inl.h"
#include "instrumentation-inl.h"
#include "intern_table-inl.h"
+#include "intern_table.h"
#include "interpreter/interpreter.h"
#include "interpreter/mterp/nterp.h"
#include "jit/debugger_interface.h"
@@ -1697,16 +1699,50 @@ static void VerifyInternedStringReferences(gc::space::ImageSpace* space)
CHECK_EQ(num_recorded_refs, num_found_refs);
}
+static bool PatchDexCacheLocations(Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches,
+ InternTable* intern_table,
+ std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Replace the location in the dex cache in the app image (the `--dex-location` passed to
+ // dex2oat) with the actual location if needed.
+ // The actual location is computed by the logic in `OatFileBase::Setup`.
+ // This is needed when the location on device is unknown at compile-time, typically during
+ // Cloud Compilation because the compilation is done on the server and the apk is later
+ // installed on device into `/data/app/<random_string>`.
+ // This is not needed during dexpreopt because the location on device is known to be a certain
+ // location in /system, /product, etc.
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ MutableHandle<mirror::DexCache> dex_cache = hs.NewHandle<mirror::DexCache>(nullptr);
+ for (auto dex_cache_ptr : dex_caches.Iterate<mirror::DexCache>()) {
+ dex_cache.Assign(dex_cache_ptr);
+ std::string dex_file_location =
+ dex_cache->GetLocation(/*allow_location_mismatch=*/true)->ToModifiedUtf8();
+ const DexFile* dex_file = dex_cache->GetDexFile();
+ if (dex_file_location != dex_file->GetLocation()) {
+ ObjPtr<mirror::String> location = intern_table->InternWeak(dex_file->GetLocation().c_str());
+ if (location == nullptr) {
+ self->AssertPendingOOMException();
+ *error_msg = "Failed to intern string for dex cache location";
+ return false;
+ }
+ dex_cache->SetLocation(location);
+ }
+ }
+ return true;
+}
+
// new_class_set is the set of classes that were read from the class table section in the image.
// If there was no class table section, it is null.
// Note: using a class here to avoid having to make ClassLinker internals public.
class AppImageLoadingHelper {
public:
- static void Update(
+ static bool Update(
ClassLinker* class_linker,
gc::space::ImageSpace* space,
Handle<mirror::ClassLoader> class_loader,
- Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches)
+ Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches,
+ InternTable* intern_table,
+ std::string* error_msg)
REQUIRES(!Locks::dex_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -1714,11 +1750,13 @@ class AppImageLoadingHelper {
REQUIRES_SHARED(Locks::mutator_lock_);
};
-void AppImageLoadingHelper::Update(
+bool AppImageLoadingHelper::Update(
ClassLinker* class_linker,
gc::space::ImageSpace* space,
Handle<mirror::ClassLoader> class_loader,
- Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches)
+ Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches,
+ InternTable* intern_table,
+ std::string* error_msg)
REQUIRES(!Locks::dex_lock_)
REQUIRES_SHARED(Locks::mutator_lock_) {
ScopedTrace app_image_timing("AppImage:Updating");
@@ -1728,6 +1766,9 @@ void AppImageLoadingHelper::Update(
// the Runtime::LoadAppImageStartupCache() option.
VerifyInternedStringReferences(space);
}
+ if (!PatchDexCacheLocations(dex_caches, intern_table, error_msg)) {
+ return false;
+ }
DCHECK(class_loader.Get() != nullptr);
Thread* const self = Thread::Current();
Runtime* const runtime = Runtime::Current();
@@ -1778,6 +1819,8 @@ void AppImageLoadingHelper::Update(
}
}, space->Begin(), kRuntimePointerSize);
}
+
+ return true;
}
void AppImageLoadingHelper::HandleAppImageStrings(gc::space::ImageSpace* space) {
@@ -1931,6 +1974,13 @@ bool ClassLinker::OpenAndInitImageDexFiles(
for (auto dex_cache : dex_caches.Iterate<mirror::DexCache>()) {
std::string dex_file_location = dex_cache->GetLocation()->ToModifiedUtf8();
+ // At this point, the location in the dex cache (from `--dex-location` passed to dex2oat) is not
+ // necessarily the actual dex location on device. `OpenOatDexFile` uses the table
+ // `OatFile::oat_dex_files_` to find the dex file. For each dex file, the table contains two
+ // keys corresponding to it, one from the oat header (from `--dex-location` passed to dex2oat)
+ // and the other being the actual dex location on device, unless they are the same. The lookup
+ // is based on the former key. Later, `PatchDexCacheLocations` will replace the location in the
+ // dex cache with the actual dex location, which is the latter key in the table.
std::unique_ptr<const DexFile> dex_file =
OpenOatDexFile(oat_file, dex_file_location.c_str(), error_msg);
if (dex_file == nullptr) {
@@ -2338,7 +2388,10 @@ bool ClassLinker::AddImageSpace(gc::space::ImageSpace* space,
VLOG(image) << "Adding class table classes took " << PrettyDuration(NanoTime() - start_time2);
}
if (app_image) {
- AppImageLoadingHelper::Update(this, space, class_loader, dex_caches);
+ if (!AppImageLoadingHelper::Update(
+ this, space, class_loader, dex_caches, intern_table_, error_msg)) {
+ return false;
+ }
{
ScopedTrace trace("AppImage:UpdateClassLoaders");