summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/gc/collector/mark_compact.cc27
1 files changed, 27 insertions, 0 deletions
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc
index 1b9217225f..91ae2bd27d 100644
--- a/runtime/gc/collector/mark_compact.cc
+++ b/runtime/gc/collector/mark_compact.cc
@@ -4013,6 +4013,33 @@ void MarkCompact::UpdateLivenessInfo(mirror::Object* obj, size_t obj_size) {
template <bool kUpdateLiveWords>
void MarkCompact::ScanObject(mirror::Object* obj) {
+ mirror::Class* klass = obj->GetClass<kVerifyNone, kWithoutReadBarrier>();
+ // TODO(lokeshgidra): Remove the following condition once b/373609505 is fixed.
+ if (UNLIKELY(klass == nullptr)) {
+ // It was seen in ConcurrentCopying GC that after a small wait when we reload
+ // the class pointer, it turns out to be a valid class object. So as a workaround,
+ // we can continue execution and log an error that this happened.
+ for (size_t i = 0; i < 1000; i++) {
+ // Wait for 1ms at a time. Don't wait for more than 1 second in total.
+ usleep(1000);
+ klass = obj->GetClass<kVerifyNone, kWithoutReadBarrier>();
+ if (klass != nullptr) {
+ std::ostringstream oss;
+ klass->DumpClass(oss, mirror::Class::kDumpClassFullDetail);
+ LOG(FATAL_WITHOUT_ABORT) << "klass pointer for obj: " << obj
+ << " found to be null first. Reloading after " << i
+ << " iterations of 1ms sleep fetched klass: " << oss.str();
+ break;
+ }
+ }
+
+ if (UNLIKELY(klass == nullptr)) {
+ // It must be heap corruption.
+ LOG(FATAL_WITHOUT_ABORT) << "klass pointer for obj: " << obj << " found to be null.";
+ }
+ heap_->GetVerification()->LogHeapCorruption(
+ obj, mirror::Object::ClassOffset(), klass, /*fatal=*/true);
+ }
// The size of `obj` is used both here (to update `bytes_scanned_`) and in
// `UpdateLivenessInfo`. As fetching this value can be expensive, do it once
// here and pass that information to `UpdateLivenessInfo`.