diff options
-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 |