diff options
| -rw-r--r-- | runtime/gc/collector/mark_compact.cc | 27 |
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`. |