Avoid dangling pointers in DexCache in jvmti redefinition.
It could be dangerous to have a DexCache holding a dangling dex file. So
just clear it if we know the dex file is going to be deleted.
Test: test.py
Change-Id: I115a733d7035778fb9cf6c34cdbb3f5889bfd735
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index a646031..0f115a5 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -554,6 +554,13 @@
if (driver_ != nullptr && lock_acquired_) {
GetMirrorClass()->MonitorExit(driver_->self_);
}
+ if (art::kIsDebugBuild) {
+ if (dex_file_ != nullptr) {
+ art::Thread* self = art::Thread::Current();
+ art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
+ CHECK(!cl->IsDexFileRegistered(self, *dex_file_));
+ }
+ }
}
template<RedefinitionType kType>
@@ -1226,6 +1233,8 @@
actually_structural_(redefinitions_->size(), false),
initial_structural_(redefinitions_->size(), false) {}
+ ~RedefinitionDataHolder() REQUIRES_SHARED(art::Locks::mutator_lock_);
+
bool IsNull() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
return arr_.IsNull();
}
@@ -1623,6 +1632,24 @@
return RedefinitionDataIter(Length(), *this);
}
+RedefinitionDataHolder::~RedefinitionDataHolder() {
+ art::Thread* self = art::Thread::Current();
+ art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
+ for (RedefinitionDataIter data = begin(); data != end(); ++data) {
+ art::ObjPtr<art::mirror::DexCache> dex_cache = data.GetNewDexCache();
+ // When redefinition fails, the dex file will be deleted in the
+ // `ClassRedefinition` destructor. To avoid having a heap `DexCache` pointing
+ // to a dangling pointer, we clear the entries of those dex caches that are
+ // not registered in the runtime.
+ if (dex_cache != nullptr &&
+ dex_cache->GetDexFile() != nullptr &&
+ !cl->IsDexFileRegistered(self, *dex_cache->GetDexFile())) {
+ dex_cache->ResetNativeArrays();
+ dex_cache->SetDexFile(nullptr);
+ }
+ }
+}
+
bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& iter) {
DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
art::StackHandleScope<3> hs(driver_->self_);
@@ -2231,6 +2258,11 @@
}
void Redefiner::ClassRedefinition::ReleaseDexFile() {
+ if (art::kIsDebugBuild) {
+ art::Thread* self = art::Thread::Current();
+ art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
+ CHECK(cl->IsDexFileRegistered(self, *dex_file_));
+ }
dex_file_.release(); // NOLINT b/117926937
}