summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2023-03-06 14:14:23 +0000
committer Nicolas Geoffray <ngeoffray@google.com> 2023-03-08 10:22:09 +0000
commit21ce03c070a14c3c5fd81bcd7e23fa06435f9ccb (patch)
treeca1f2dfd6887dc9224acfbe3ef90540e7f5ddd88 /runtime/class_linker.cc
parente6c839354e623ecb030d95e5333b5df84b7953dd (diff)
Fix races related to dex caches in runtime app images.
- Make sure dex cache arrays are properly aligned. - Handle dex cache arrays being concurrently cleared when loading an image. - Don't use memcpy but update entries one by one when generating the image. Test: test.py Bug: 260557058 Change-Id: I5ef72a7363fe5e108f62d03caa399e5300cf7a55
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc23
1 files changed, 17 insertions, 6 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b00910fec8..8927c4337e 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1587,12 +1587,15 @@ static void VisitInternedStringReferences(
if (obj_ptr->IsDexCache() && raw_member_offset >= sizeof(mirror::DexCache)) {
// Special case for strings referenced from dex cache array.
uint32_t offset = raw_member_offset - sizeof(mirror::DexCache);
- ObjPtr<mirror::String> referred_string =
- obj_ptr->AsDexCache()->GetStringsArray()->Get(offset);
- DCHECK(referred_string != nullptr);
- ObjPtr<mirror::String> visited = visitor(referred_string);
- if (visited != referred_string) {
- obj_ptr->AsDexCache()->GetStringsArray()->Set(offset, visited.Ptr());
+ mirror::GcRootArray<mirror::String>* array = obj_ptr->AsDexCache()->GetStringsArray();
+ // The array could be concurrently set to null. See `StartupCompletedTask`.
+ if (array != nullptr) {
+ ObjPtr<mirror::String> referred_string = array->Get(offset);
+ DCHECK(referred_string != nullptr);
+ ObjPtr<mirror::String> visited = visitor(referred_string);
+ if (visited != referred_string) {
+ obj_ptr->AsDexCache()->GetStringsArray()->Set(offset, visited.Ptr());
+ }
}
} else {
DCHECK_ALIGNED(raw_member_offset, 2);
@@ -1705,6 +1708,14 @@ void AppImageLoadingHelper::Update(
}
}, space->Begin(), kRuntimePointerSize);
}
+
+ if (runtime->GetStartupCompleted()) {
+ // Free up dex cache arrays that we would only allocate at startup.
+ for (auto dex_cache : dex_caches.Iterate<mirror::DexCache>()) {
+ dex_cache->UnlinkStartupCaches();
+ }
+ space->ReleaseMetadata();
+ }
}
void AppImageLoadingHelper::HandleAppImageStrings(gc::space::ImageSpace* space) {