Handle cleared preresolved strings
The profile saver can theoretically result in the preresolved strings
being cleared before they are updated. Since the clearing process
nulls the array, it was causing a null pointer dereference in some
cases.
Bug: 134698657
Test: test-art-host
Change-Id: I9c260bbfded26e9481381e9978596907e48c3307
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b2e7d99..b40d61f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1477,15 +1477,22 @@
reinterpret_cast<mirror::DexCache*>(space->Begin() + base_offset);
uint32_t string_index = sro_base[offset_index].second;
- ObjPtr<mirror::String> referred_string =
- dex_cache->GetPreResolvedStrings()[string_index].Read();
- DCHECK(referred_string != nullptr);
-
- ObjPtr<mirror::String> visited = visitor(referred_string);
- if (visited != referred_string) {
- // Because we are not using a helper function we need to mark the GC card manually.
- WriteBarrier::ForEveryFieldWrite(dex_cache);
- dex_cache->GetPreResolvedStrings()[string_index] = GcRoot<mirror::String>(visited);
+ GcRoot<mirror::String>* preresolved_strings =
+ dex_cache->GetPreResolvedStrings();
+ // Handle calls to ClearPreResolvedStrings that might occur concurrently by the profile
+ // saver that runs shortly after startup. In case the strings are cleared, there is nothing
+ // to fix up.
+ if (preresolved_strings != nullptr) {
+ ObjPtr<mirror::String> referred_string =
+ preresolved_strings[string_index].Read();
+ if (referred_string != nullptr) {
+ ObjPtr<mirror::String> visited = visitor(referred_string);
+ if (visited != referred_string) {
+ // Because we are not using a helper function we need to mark the GC card manually.
+ WriteBarrier::ForEveryFieldWrite(dex_cache);
+ preresolved_strings[string_index] = GcRoot<mirror::String>(visited);
+ }
+ }
}
}
} else {