summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/object_utils.h10
-rw-r--r--runtime/proxy_test.cc65
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