summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/class_linker.cc132
-rw-r--r--runtime/class_linker.h6
-rw-r--r--runtime/gc/collector/mark_sweep.cc9
-rw-r--r--runtime/mirror/field.cc1
4 files changed, 81 insertions, 67 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 491c910e0c..fe220a9027 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1822,8 +1822,8 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, si
// TODO: Use fast jobjects?
auto interfaces = hs.NewHandle<mirror::ObjectArray<mirror::Class>>(nullptr);
- mirror::Class* new_class = nullptr;
- if (!LinkClass(self, descriptor, klass, interfaces, &new_class)) {
+ MutableHandle<mirror::Class> h_new_class = hs.NewHandle<mirror::Class>(nullptr);
+ if (!LinkClass(self, descriptor, klass, interfaces, &h_new_class)) {
// Linking failed.
if (!klass->IsErroneous()) {
mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
@@ -1831,10 +1831,8 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, si
return nullptr;
}
self->AssertNoPendingException();
- CHECK(new_class != nullptr) << descriptor;
- CHECK(new_class->IsResolved()) << descriptor;
-
- Handle<mirror::Class> new_class_h(hs.NewHandle(new_class));
+ CHECK(h_new_class.Get() != nullptr) << descriptor;
+ CHECK(h_new_class->IsResolved()) << descriptor;
// Instrumentation may have updated entrypoints for all methods of all
// classes. However it could not update methods of this class while we
@@ -1845,7 +1843,7 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, si
// suspending all threads to update entrypoints while we are doing it
// for this class.
DCHECK_EQ(self->GetState(), kRunnable);
- Runtime::Current()->GetInstrumentation()->InstallStubsForClass(new_class_h.Get());
+ Runtime::Current()->GetInstrumentation()->InstallStubsForClass(h_new_class.Get());
}
/*
@@ -1859,9 +1857,9 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, si
* The class has been prepared and resolved but possibly not yet verified
* at this point.
*/
- Dbg::PostClassPrepare(new_class_h.Get());
+ Dbg::PostClassPrepare(h_new_class.Get());
- return new_class_h.Get();
+ return h_new_class.Get();
}
uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
@@ -2745,11 +2743,7 @@ mirror::Class* ClassLinker::UpdateClass(const char* descriptor, mirror::Class* k
WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
auto existing_it = class_table_.FindWithHash(std::make_pair(descriptor, klass->GetClassLoader()),
hash);
- if (existing_it == class_table_.end()) {
- CHECK(klass->IsProxyClass());
- return nullptr;
- }
-
+ CHECK(existing_it != class_table_.end());
mirror::Class* existing = existing_it->Read();
CHECK_NE(existing, klass) << descriptor;
CHECK(!existing->IsResolved()) << descriptor;
@@ -3221,7 +3215,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
jobjectArray interfaces, jobject loader,
jobjectArray methods, jobjectArray throws) {
Thread* self = soa.Self();
- StackHandleScope<9> hs(self);
+ StackHandleScope<10> hs(self);
MutableHandle<mirror::Class> klass(hs.NewHandle(
AllocClass(self, GetClassRoot(kJavaLangClass), sizeof(mirror::Class))));
if (klass.Get() == nullptr) {
@@ -3235,9 +3229,17 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
klass->SetClassLoader(soa.Decode<mirror::ClassLoader*>(loader));
DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot);
klass->SetName(soa.Decode<mirror::String*>(name));
- mirror::Class* proxy_class = GetClassRoot(kJavaLangReflectProxy);
- klass->SetDexCache(proxy_class->GetDexCache());
+ klass->SetDexCache(GetClassRoot(kJavaLangReflectProxy)->GetDexCache());
mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, self);
+ std::string descriptor(GetDescriptorForProxy(klass.Get()));
+ size_t hash = ComputeModifiedUtf8Hash(descriptor.c_str());
+
+ // Insert the class before loading the fields as the field roots
+ // (ArtField::declaring_class_) are only visited from the class
+ // table. There can't be any suspend points between inserting the
+ // class and setting the field arrays below.
+ mirror::Class* existing = InsertClass(descriptor.c_str(), klass.Get(), hash);
+ CHECK(existing == nullptr);
// Instance fields are inherited, but we add a couple of static fields...
const size_t num_fields = 2;
@@ -3260,18 +3262,21 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
// Proxies have 1 direct method, the constructor
{
- mirror::ObjectArray<mirror::ArtMethod>* directs = AllocArtMethodArray(self, 1);
- if (UNLIKELY(directs == nullptr)) {
+ StackHandleScope<2> hs2(self);
+ Handle<mirror::ObjectArray<mirror::ArtMethod>> directs =
+ hs2.NewHandle(AllocArtMethodArray(self, 1));
+ if (UNLIKELY(directs.Get() == nullptr)) {
CHECK(self->IsExceptionPending()); // OOME.
return nullptr;
}
- klass->SetDirectMethods(directs);
- mirror::ArtMethod* constructor = CreateProxyConstructor(self, klass, proxy_class);
- if (UNLIKELY(constructor == nullptr)) {
+ klass->SetDirectMethods(directs.Get());
+ Handle<mirror::ArtMethod> constructor =
+ hs2.NewHandle(CreateProxyConstructor(self, klass));
+ if (UNLIKELY(constructor.Get() == nullptr)) {
CHECK(self->IsExceptionPending()); // OOME.
return nullptr;
}
- klass->SetDirectMethod(0, constructor);
+ klass->SetDirectMethod(0, constructor.Get());
}
// Create virtual method using specified prototypes.
@@ -3280,35 +3285,38 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
<< PrettyClass(h_methods->GetClass());
const size_t num_virtual_methods = h_methods->GetLength();
{
- mirror::ObjectArray<mirror::ArtMethod>* virtuals = AllocArtMethodArray(self,
- num_virtual_methods);
- if (UNLIKELY(virtuals == nullptr)) {
+ StackHandleScope<1> hs2(self);
+ Handle<mirror::ObjectArray<mirror::ArtMethod>> virtuals =
+ hs2.NewHandle(AllocArtMethodArray(self, num_virtual_methods));
+ if (UNLIKELY(virtuals.Get() == nullptr)) {
CHECK(self->IsExceptionPending()); // OOME.
return nullptr;
}
- klass->SetVirtualMethods(virtuals);
+ klass->SetVirtualMethods(virtuals.Get());
}
for (size_t i = 0; i < num_virtual_methods; ++i) {
- StackHandleScope<1> hs2(self);
+ StackHandleScope<2> hs2(self);
Handle<mirror::ArtMethod> prototype(hs2.NewHandle(h_methods->Get(i)->GetArtMethod()));
- mirror::ArtMethod* clone = CreateProxyMethod(self, klass, prototype);
- if (UNLIKELY(clone == nullptr)) {
+ Handle<mirror::ArtMethod> clone(hs2.NewHandle(CreateProxyMethod(self, klass, prototype)));
+ if (UNLIKELY(clone.Get() == nullptr)) {
CHECK(self->IsExceptionPending()); // OOME.
return nullptr;
}
- klass->SetVirtualMethod(i, clone);
+ klass->SetVirtualMethod(i, clone.Get());
}
- klass->SetSuperClass(proxy_class); // The super class is java.lang.reflect.Proxy
- mirror::Class::SetStatus(klass, mirror::Class::kStatusLoaded, self); // Now effectively in the loaded state.
+ // The super class is java.lang.reflect.Proxy
+ klass->SetSuperClass(GetClassRoot(kJavaLangReflectProxy));
+ // Now effectively in the loaded state.
+ mirror::Class::SetStatus(klass, mirror::Class::kStatusLoaded, self);
self->AssertNoPendingException();
- std::string descriptor(GetDescriptorForProxy(klass.Get()));
- mirror::Class* new_class = nullptr;
+ MutableHandle<mirror::Class> new_class = hs.NewHandle<mirror::Class>(nullptr);
{
// Must hold lock on object when resolved.
ObjectLock<mirror::Class> resolution_lock(self, klass);
- // Link the fields and virtual methods, creating vtable and iftables
+ // Link the fields and virtual methods, creating vtable and iftables.
+ // The new class will replace the old one in the class table.
Handle<mirror::ObjectArray<mirror::Class> > h_interfaces(
hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces)));
if (!LinkClass(self, descriptor.c_str(), klass, h_interfaces, &new_class)) {
@@ -3316,15 +3324,14 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
return nullptr;
}
}
-
CHECK(klass->IsRetired());
- CHECK_NE(klass.Get(), new_class);
- klass.Assign(new_class);
+ CHECK_NE(klass.Get(), new_class.Get());
+ klass.Assign(new_class.Get());
- CHECK_EQ(interfaces_sfield->GetDeclaringClass(), new_class);
+ CHECK_EQ(interfaces_sfield->GetDeclaringClass(), klass.Get());
interfaces_sfield->SetObject<false>(klass.Get(),
soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
- CHECK_EQ(throws_sfield->GetDeclaringClass(), new_class);
+ CHECK_EQ(throws_sfield->GetDeclaringClass(), klass.Get());
throws_sfield->SetObject<false>(klass.Get(),
soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >*>(throws));
@@ -3345,7 +3352,8 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
CheckProxyMethod(virtual_method, prototype);
}
- mirror::String* decoded_name = soa.Decode<mirror::String*>(name);
+ StackHandleScope<1> hs2(self);
+ Handle<mirror::String> decoded_name = hs2.NewHandle(soa.Decode<mirror::String*>(name));
std::string interfaces_field_name(StringPrintf("java.lang.Class[] %s.interfaces",
decoded_name->ToModifiedUtf8().c_str()));
CHECK_EQ(PrettyField(klass->GetStaticField(0)), interfaces_field_name);
@@ -3359,9 +3367,6 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
CHECK_EQ(klass.Get()->GetThrows(),
soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class>>*>(throws));
}
- mirror::Class* existing = InsertClass(descriptor.c_str(), klass.Get(),
- ComputeModifiedUtf8Hash(descriptor.c_str()));
- CHECK(existing == nullptr);
return klass.Get();
}
@@ -3396,17 +3401,16 @@ mirror::ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class,
mirror::ArtMethod* ClassLinker::CreateProxyConstructor(Thread* self,
- Handle<mirror::Class> klass,
- mirror::Class* proxy_class) {
+ Handle<mirror::Class> klass) {
// Create constructor for Proxy that must initialize h
mirror::ObjectArray<mirror::ArtMethod>* proxy_direct_methods =
- proxy_class->GetDirectMethods();
+ GetClassRoot(kJavaLangReflectProxy)->GetDirectMethods();
CHECK_EQ(proxy_direct_methods->GetLength(), 16);
mirror::ArtMethod* proxy_constructor = proxy_direct_methods->Get(2);
// Ensure constructor is in dex cache so that we can use the dex cache to look up the overridden
// constructor method.
- proxy_class->GetDexCache()->SetResolvedMethod(proxy_constructor->GetDexMethodIndex(),
- proxy_constructor);
+ GetClassRoot(kJavaLangReflectProxy)->GetDexCache()->SetResolvedMethod(
+ proxy_constructor->GetDexMethodIndex(), proxy_constructor);
// Clone the existing constructor of Proxy (our constructor would just invoke it so steal its
// code_ too)
mirror::ArtMethod* constructor = down_cast<mirror::ArtMethod*>(proxy_constructor->Clone(self));
@@ -3930,7 +3934,7 @@ void ClassLinker::FixupTemporaryDeclaringClass(mirror::Class* temp_class, mirror
bool ClassLinker::LinkClass(Thread* self, const char* descriptor, Handle<mirror::Class> klass,
Handle<mirror::ObjectArray<mirror::Class>> interfaces,
- mirror::Class** new_class) {
+ MutableHandle<mirror::Class>* h_new_class_out) {
CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());
if (!LinkSuperClass(klass)) {
@@ -3963,25 +3967,23 @@ bool ClassLinker::LinkClass(Thread* self, const char* descriptor, Handle<mirror:
// This will notify waiters on klass that saw the not yet resolved
// class in the class_table_ during EnsureResolved.
mirror::Class::SetStatus(klass, mirror::Class::kStatusResolved, self);
- *new_class = klass.Get();
+ h_new_class_out->Assign(klass.Get());
} else {
CHECK(!klass->IsResolved());
// Retire the temporary class and create the correctly sized resolved class.
- *new_class = klass->CopyOf(self, class_size, &imt_handle_scope);
- if (UNLIKELY(*new_class == nullptr)) {
+ StackHandleScope<1> hs(self);
+ auto h_new_class = hs.NewHandle<mirror::Class>(
+ klass->CopyOf(self, class_size, &imt_handle_scope));
+ if (UNLIKELY(h_new_class.Get() == nullptr)) {
CHECK(self->IsExceptionPending()); // Expect an OOME.
mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
return false;
}
- CHECK_EQ((*new_class)->GetClassSize(), class_size);
- StackHandleScope<1> hs(self);
- auto new_class_h = hs.NewHandleWrapper<mirror::Class>(new_class);
- ObjectLock<mirror::Class> lock(self, new_class_h);
-
- FixupTemporaryDeclaringClass(klass.Get(), new_class_h.Get());
-
- mirror::Class* existing = UpdateClass(descriptor, new_class_h.Get(),
+ CHECK_EQ(h_new_class->GetClassSize(), class_size);
+ ObjectLock<mirror::Class> lock(self, h_new_class);
+ FixupTemporaryDeclaringClass(klass.Get(), h_new_class.Get());
+ mirror::Class* existing = UpdateClass(descriptor, h_new_class.Get(),
ComputeModifiedUtf8Hash(descriptor));
CHECK(existing == nullptr || existing == klass.Get());
@@ -3989,10 +3991,12 @@ bool ClassLinker::LinkClass(Thread* self, const char* descriptor, Handle<mirror:
// class_table_ during EnsureResolved.
mirror::Class::SetStatus(klass, mirror::Class::kStatusRetired, self);
- CHECK_EQ(new_class_h->GetStatus(), mirror::Class::kStatusResolving);
+ CHECK_EQ(h_new_class->GetStatus(), mirror::Class::kStatusResolving);
// This will notify waiters on new_class that saw the not yet resolved
// class in the class_table_ during EnsureResolved.
- mirror::Class::SetStatus(new_class_h, mirror::Class::kStatusResolved, self);
+ mirror::Class::SetStatus(h_new_class, mirror::Class::kStatusResolved, self);
+ // Return the new class.
+ h_new_class_out->Assign(h_new_class.Get());
}
return true;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 95c8aa0244..947e15210b 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -49,6 +49,7 @@ namespace mirror {
} // namespace mirror
template<class T> class Handle;
+template<class T> class MutableHandle;
class InternTable;
template<class T> class ObjectLock;
class Runtime;
@@ -572,7 +573,7 @@ class ClassLinker {
bool LinkClass(Thread* self, const char* descriptor, Handle<mirror::Class> klass,
Handle<mirror::ObjectArray<mirror::Class>> interfaces,
- mirror::Class** new_class)
+ MutableHandle<mirror::Class>* h_new_class_out)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool LinkSuperClass(Handle<mirror::Class> klass)
@@ -622,8 +623,7 @@ class ClassLinker {
// Returns the boot image oat file.
const OatFile* GetBootOatFile() SHARED_LOCKS_REQUIRED(dex_lock_);
- mirror::ArtMethod* CreateProxyConstructor(Thread* self, Handle<mirror::Class> klass,
- mirror::Class* proxy_class)
+ mirror::ArtMethod* CreateProxyConstructor(Thread* self, Handle<mirror::Class> klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::ArtMethod* CreateProxyMethod(Thread* self, Handle<mirror::Class> klass,
Handle<mirror::ArtMethod> prototype)
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 5401b56449..2db5650b0b 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -389,6 +389,9 @@ class MarkSweepMarkObjectSlowPath {
ArtField* field = holder_->FindFieldByOffset(offset_);
LOG(INTERNAL_FATAL) << "Field info: "
<< " holder=" << holder_
+ << " holder is "
+ << (mark_sweep_->GetHeap()->IsLiveObjectLocked(holder_)
+ ? "alive" : "dead")
<< " holder_size=" << holder_size
<< " holder_type=" << PrettyTypeOf(holder_)
<< " offset=" << offset_.Uint32Value()
@@ -404,6 +407,12 @@ class MarkSweepMarkObjectSlowPath {
? holder_->AsClass()->NumReferenceStaticFields()
: holder_->GetClass()->NumReferenceInstanceFields())
<< "\n";
+ // Print the memory content of the holder.
+ for (size_t i = 0; i < holder_size / sizeof(uint32_t); ++i) {
+ uint32_t* p = reinterpret_cast<uint32_t*>(holder_);
+ LOG(INTERNAL_FATAL) << &p[i] << ": " << "holder+" << (i * sizeof(uint32_t)) << " = "
+ << std::hex << p[i];
+ }
}
PrintFileToLog("/proc/self/maps", LogSeverity::INTERNAL_FATAL);
MemMap::DumpMaps(LOG(INTERNAL_FATAL), true);
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
index 933784e7ff..ac56129a16 100644
--- a/runtime/mirror/field.cc
+++ b/runtime/mirror/field.cc
@@ -69,6 +69,7 @@ ArtField* Field::GetArtField() {
mirror::DexCache* const dex_cache = declaring_class->GetDexCache();
ArtField* const art_field = dex_cache->GetResolvedField(GetDexFieldIndex(), sizeof(void*));
CHECK(art_field != nullptr);
+ CHECK_EQ(declaring_class, art_field->GetDeclaringClass());
return art_field;
}