1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "dex_cache.h" 18 19 #include <stdio.h> 20 21 #include "art_method-inl.h" 22 #include "class_linker.h" 23 #include "common_runtime_test.h" 24 #include "handle_scope-inl.h" 25 #include "linear_alloc.h" 26 #include "mirror/class_loader-inl.h" 27 #include "mirror/dex_cache-inl.h" 28 #include "scoped_thread_state_change-inl.h" 29 30 namespace art { 31 namespace mirror { 32 33 class DexCacheTest : public CommonRuntimeTest {}; 34 35 class DexCacheMethodHandlesTest : public DexCacheTest { 36 protected: 37 void SetUpRuntimeOptions(RuntimeOptions* options) override { 38 CommonRuntimeTest::SetUpRuntimeOptions(options); 39 } 40 }; 41 42 TEST_F(DexCacheTest, Open) { 43 ScopedObjectAccess soa(Thread::Current()); 44 StackHandleScope<1> hs(soa.Self()); 45 ASSERT_TRUE(java_lang_dex_file_ != nullptr); 46 Handle<DexCache> dex_cache( 47 hs.NewHandle(class_linker_->AllocAndInitializeDexCache( 48 soa.Self(), 49 *java_lang_dex_file_, 50 Runtime::Current()->GetLinearAlloc()))); 51 ASSERT_TRUE(dex_cache != nullptr); 52 53 EXPECT_TRUE(dex_cache->StaticStringSize() == dex_cache->NumStrings() 54 || java_lang_dex_file_->NumStringIds() == dex_cache->NumStrings()); 55 EXPECT_TRUE(dex_cache->StaticTypeSize() == dex_cache->NumResolvedTypes() 56 || java_lang_dex_file_->NumTypeIds() == dex_cache->NumResolvedTypes()); 57 EXPECT_TRUE(dex_cache->StaticMethodSize() == dex_cache->NumResolvedMethods() 58 || java_lang_dex_file_->NumMethodIds() == dex_cache->NumResolvedMethods()); 59 EXPECT_TRUE(dex_cache->StaticArtFieldSize() == dex_cache->NumResolvedFields() 60 || java_lang_dex_file_->NumFieldIds() == dex_cache->NumResolvedFields()); 61 EXPECT_TRUE(dex_cache->StaticMethodTypeSize() == dex_cache->NumResolvedMethodTypes() 62 || java_lang_dex_file_->NumProtoIds() == dex_cache->NumResolvedMethodTypes()); 63 } 64 65 TEST_F(DexCacheMethodHandlesTest, Open) { 66 ScopedObjectAccess soa(Thread::Current()); 67 StackHandleScope<1> hs(soa.Self()); 68 ASSERT_TRUE(java_lang_dex_file_ != nullptr); 69 Handle<DexCache> dex_cache( 70 hs.NewHandle(class_linker_->AllocAndInitializeDexCache( 71 soa.Self(), 72 *java_lang_dex_file_, 73 Runtime::Current()->GetLinearAlloc()))); 74 75 EXPECT_TRUE(dex_cache->StaticMethodTypeSize() == dex_cache->NumResolvedMethodTypes() 76 || java_lang_dex_file_->NumProtoIds() == dex_cache->NumResolvedMethodTypes()); 77 } 78 79 TEST_F(DexCacheTest, LinearAlloc) { 80 ScopedObjectAccess soa(Thread::Current()); 81 jobject jclass_loader(LoadDex("Main")); 82 ASSERT_TRUE(jclass_loader != nullptr); 83 StackHandleScope<1> hs(soa.Self()); 84 Handle<mirror::ClassLoader> class_loader(hs.NewHandle( 85 soa.Decode<mirror::ClassLoader>(jclass_loader))); 86 ObjPtr<mirror::Class> klass = class_linker_->FindClass(soa.Self(), "LMain;", class_loader); 87 ASSERT_TRUE(klass != nullptr); 88 LinearAlloc* const linear_alloc = klass->GetClassLoader()->GetAllocator(); 89 EXPECT_NE(linear_alloc, runtime_->GetLinearAlloc()); 90 EXPECT_TRUE(linear_alloc->Contains(klass->GetDexCache()->GetResolvedMethods())); 91 } 92 93 TEST_F(DexCacheTest, TestResolvedFieldAccess) { 94 ScopedObjectAccess soa(Thread::Current()); 95 jobject jclass_loader(LoadDex("Packages")); 96 ASSERT_TRUE(jclass_loader != nullptr); 97 StackHandleScope<3> hs(soa.Self()); 98 Handle<mirror::ClassLoader> class_loader(hs.NewHandle( 99 soa.Decode<mirror::ClassLoader>(jclass_loader))); 100 Handle<mirror::Class> klass1 = 101 hs.NewHandle(class_linker_->FindClass(soa.Self(), "Lpackage1/Package1;", class_loader)); 102 ASSERT_TRUE(klass1 != nullptr); 103 Handle<mirror::Class> klass2 = 104 hs.NewHandle(class_linker_->FindClass(soa.Self(), "Lpackage2/Package2;", class_loader)); 105 ASSERT_TRUE(klass2 != nullptr); 106 EXPECT_OBJ_PTR_EQ(klass1->GetDexCache(), klass2->GetDexCache()); 107 108 EXPECT_NE(klass1->NumStaticFields(), 0u); 109 for (ArtField& field : klass2->GetSFields()) { 110 EXPECT_FALSE( 111 klass1->ResolvedFieldAccessTest</*throw_on_failure=*/ false>( 112 klass2.Get(), 113 &field, 114 klass1->GetDexCache(), 115 field.GetDexFieldIndex())); 116 } 117 } 118 119 TEST_F(DexCacheMethodHandlesTest, TestResolvedMethodTypes) { 120 ScopedObjectAccess soa(Thread::Current()); 121 jobject jclass_loader(LoadDex("MethodTypes")); 122 ASSERT_TRUE(jclass_loader != nullptr); 123 124 StackHandleScope<5> hs(soa.Self()); 125 Handle<mirror::ClassLoader> class_loader(hs.NewHandle( 126 soa.Decode<mirror::ClassLoader>(jclass_loader))); 127 128 Handle<mirror::Class> method_types( 129 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LMethodTypes;", class_loader))); 130 class_linker_->EnsureInitialized(soa.Self(), method_types, true, true); 131 132 ArtMethod* method1 = method_types->FindClassMethod( 133 "method1", 134 "(Ljava/lang/String;)Ljava/lang/String;", 135 kRuntimePointerSize); 136 ASSERT_TRUE(method1 != nullptr); 137 ASSERT_FALSE(method1->IsDirect()); 138 ArtMethod* method2 = method_types->FindClassMethod( 139 "method2", 140 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", 141 kRuntimePointerSize); 142 ASSERT_TRUE(method2 != nullptr); 143 ASSERT_FALSE(method2->IsDirect()); 144 145 const DexFile& dex_file = *(method1->GetDexFile()); 146 Handle<mirror::DexCache> dex_cache = hs.NewHandle( 147 class_linker_->FindDexCache(Thread::Current(), dex_file)); 148 149 const dex::MethodId& method1_id = dex_file.GetMethodId(method1->GetDexMethodIndex()); 150 const dex::MethodId& method2_id = dex_file.GetMethodId(method2->GetDexMethodIndex()); 151 Handle<mirror::MethodType> method1_type = hs.NewHandle( 152 class_linker_->ResolveMethodType(soa.Self(), 153 method1_id.proto_idx_, 154 dex_cache, 155 class_loader)); 156 Handle<mirror::MethodType> method2_type = hs.NewHandle( 157 class_linker_->ResolveMethodType(soa.Self(), 158 method2_id.proto_idx_, 159 dex_cache, 160 class_loader)); 161 EXPECT_EQ(method1_type.Get(), dex_cache->GetResolvedMethodType(method1_id.proto_idx_)); 162 EXPECT_EQ(method2_type.Get(), dex_cache->GetResolvedMethodType(method2_id.proto_idx_)); 163 164 // The MethodTypes dex file contains a single interface with two abstract 165 // methods. It must therefore contain precisely two method IDs. 166 ASSERT_EQ(2u, dex_file.NumProtoIds()); 167 ASSERT_EQ(dex_file.NumProtoIds(), dex_cache->NumResolvedMethodTypes()); 168 MethodTypeDexCacheType* method_types_cache = dex_cache->GetResolvedMethodTypes(); 169 170 for (size_t i = 0; i < dex_file.NumProtoIds(); ++i) { 171 const MethodTypeDexCachePair pair = method_types_cache[i].load(std::memory_order_relaxed); 172 if (dex::ProtoIndex(pair.index) == method1_id.proto_idx_) { 173 ASSERT_EQ(method1_type.Get(), pair.object.Read()); 174 } else if (dex::ProtoIndex(pair.index) == method2_id.proto_idx_) { 175 ASSERT_EQ(method2_type.Get(), pair.object.Read()); 176 } else { 177 ASSERT_TRUE(false); 178 } 179 } 180 } 181 182 } // namespace mirror 183 } // namespace art 184