diff options
author | 2014-04-01 14:39:44 +0200 | |
---|---|---|
committer | 2014-04-01 15:20:11 +0200 | |
commit | 80989a6bf3e24b31c7210c76be81ad40f43c63be (patch) | |
tree | 6e3365de360d3d02c14ce614e1755620e8b9f7bb | |
parent | a708e32a9f764a48175e705ec4bcd2201c84f492 (diff) |
Fix ClassHelper::GetDirectInterface for proxy class
Returns only the direct interfaces implemented by the proxy class. We collect
them from the "interfaces" field in the synthesized proxy class instead of
looking into the iftable.
Also updates proxy_test to reflect this change.
Bug: 13689930
Change-Id: I926e2ed30f9e65972d700a378671cec82dedaa7c
-rw-r--r-- | runtime/object_utils.h | 10 | ||||
-rw-r--r-- | runtime/proxy_test.cc | 65 |
2 files changed, 64 insertions, 11 deletions
diff --git a/runtime/object_utils.h b/runtime/object_utils.h index 63801d3a3f..072f074e85 100644 --- a/runtime/object_utils.h +++ b/runtime/object_utils.h @@ -25,6 +25,7 @@ #include "mirror/class.h" #include "mirror/dex_cache.h" #include "mirror/iftable.h" +#include "mirror/proxy.h" #include "mirror/string.h" #include "runtime.h" @@ -133,7 +134,9 @@ class ClassHelper { } else if (klass_->IsArrayClass()) { return 2; } else if (klass_->IsProxyClass()) { - return klass_->GetIfTable()->Count(); + mirror::SynthesizedProxyClass* proxyClass = reinterpret_cast<mirror::SynthesizedProxyClass*>(klass_); + mirror::ObjectArray<mirror::Class>* interfaces = proxyClass->GetInterfaces(); + return interfaces != nullptr ? interfaces->GetLength() : 0; } else { const DexFile::TypeList* interfaces = GetInterfaceTypeList(); if (interfaces == nullptr) { @@ -164,7 +167,10 @@ class ClassHelper { return GetClassLinker()->FindSystemClass(Thread::Current(), "Ljava/io/Serializable;"); } } else if (klass_->IsProxyClass()) { - return klass_->GetIfTable()->GetInterface(idx); + mirror::SynthesizedProxyClass* proxyClass = reinterpret_cast<mirror::SynthesizedProxyClass*>(klass_); + mirror::ObjectArray<mirror::Class>* interfaces = proxyClass->GetInterfaces(); + DCHECK(interfaces != nullptr); + return interfaces->Get(idx); } else { uint16_t type_idx = GetDirectInterfaceTypeIdx(idx); mirror::Class* interface = GetDexCache()->GetResolvedType(type_idx); diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc index 6453cb4d48..eebfba8798 100644 --- a/runtime/proxy_test.cc +++ b/runtime/proxy_test.cc @@ -107,7 +107,8 @@ class ProxyTest : public CommonCompilerTest { TEST_F(ProxyTest, ProxyClassHelper) { ScopedObjectAccess soa(Thread::Current()); jobject jclass_loader = LoadDex("Interfaces"); - SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(jclass_loader)); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), + soa.Decode<mirror::ClassLoader*>(jclass_loader)); mirror::Class* I = class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader); mirror::Class* J = class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader); @@ -120,20 +121,66 @@ TEST_F(ProxyTest, ProxyClassHelper) { mirror::Class* proxyClass = GenerateProxyClass(soa, jclass_loader, "$Proxy1234", interfaces); ASSERT_TRUE(proxyClass != nullptr); ASSERT_TRUE(proxyClass->IsProxyClass()); - - mirror::Class* javaIoSerializable = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;"); - ASSERT_TRUE(javaIoSerializable != nullptr); + ASSERT_TRUE(proxyClass->IsInitialized()); // Check ClassHelper for proxy. ClassHelper kh(proxyClass); - EXPECT_EQ(kh.NumDirectInterfaces(), 3U); // java.io.Serializable, Interfaces$I and Interfaces$J. - EXPECT_EQ(javaIoSerializable, kh.GetDirectInterface(0)); - EXPECT_EQ(I, kh.GetDirectInterface(1)); - EXPECT_EQ(J, kh.GetDirectInterface(2)); + EXPECT_EQ(kh.NumDirectInterfaces(), 2U); // Interfaces$I and Interfaces$J. + EXPECT_EQ(I, kh.GetDirectInterface(0)); + EXPECT_EQ(J, kh.GetDirectInterface(1)); std::string proxyClassDescriptor(kh.GetDescriptor()); EXPECT_EQ("L$Proxy1234;", proxyClassDescriptor); -// EXPECT_EQ(nullptr, kh.GetSourceFile()); } +// Creates a proxy class and check FieldHelper works correctly. +TEST_F(ProxyTest, ProxyFieldHelper) { + ScopedObjectAccess soa(Thread::Current()); + jobject jclass_loader = LoadDex("Interfaces"); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), + soa.Decode<mirror::ClassLoader*>(jclass_loader)); + + mirror::Class* I = class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader); + mirror::Class* J = class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader); + ASSERT_TRUE(I != nullptr); + ASSERT_TRUE(J != nullptr); + std::vector<mirror::Class*> interfaces; + interfaces.push_back(I); + interfaces.push_back(J); + + mirror::Class* proxyClass = GenerateProxyClass(soa, jclass_loader, "$Proxy1234", interfaces); + ASSERT_TRUE(proxyClass != nullptr); + ASSERT_TRUE(proxyClass->IsProxyClass()); + ASSERT_TRUE(proxyClass->IsInitialized()); + + mirror::ObjectArray<mirror::ArtField>* instance_fields = proxyClass->GetIFields(); + EXPECT_TRUE(instance_fields == nullptr); + + mirror::ObjectArray<mirror::ArtField>* static_fields = proxyClass->GetSFields(); + ASSERT_TRUE(static_fields != nullptr); + ASSERT_EQ(2, static_fields->GetLength()); + + mirror::Class* interfacesFieldClass = class_linker_->FindSystemClass(soa.Self(), + "[Ljava/lang/Class;"); + ASSERT_TRUE(interfacesFieldClass != nullptr); + mirror::Class* throwsFieldClass = class_linker_->FindSystemClass(soa.Self(), + "[[Ljava/lang/Class;"); + ASSERT_TRUE(throwsFieldClass != nullptr); + + // Test "Class[] interfaces" field. + FieldHelper fh(static_fields->Get(0)); + EXPECT_EQ("interfaces", std::string(fh.GetName())); + EXPECT_EQ("[Ljava/lang/Class;", std::string(fh.GetTypeDescriptor())); + EXPECT_EQ(interfacesFieldClass, fh.GetType()); + EXPECT_EQ("L$Proxy1234;", std::string(fh.GetDeclaringClassDescriptor())); + EXPECT_FALSE(fh.IsPrimitiveType()); + + // Test "Class[][] throws" field. + fh.ChangeField(static_fields->Get(1)); + EXPECT_EQ("throws", std::string(fh.GetName())); + EXPECT_EQ("[[Ljava/lang/Class;", std::string(fh.GetTypeDescriptor())); + EXPECT_EQ(throwsFieldClass, fh.GetType()); + EXPECT_EQ("L$Proxy1234;", std::string(fh.GetDeclaringClassDescriptor())); + EXPECT_FALSE(fh.IsPrimitiveType()); +} } // namespace art |