1 /* 2 * Copyright (C) 2016 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 "class_table-inl.h" 18 19 #include "art_field-inl.h" 20 #include "art_method-inl.h" 21 #include "class_linker-inl.h" 22 #include "common_runtime_test.h" 23 #include "dex/dex_file.h" 24 #include "gc/accounting/card_table-inl.h" 25 #include "gc/heap.h" 26 #include "handle_scope-inl.h" 27 #include "mirror/class-inl.h" 28 #include "obj_ptr.h" 29 #include "scoped_thread_state_change-inl.h" 30 31 namespace art { 32 namespace mirror { 33 34 class CollectRootVisitor { 35 public: 36 CollectRootVisitor() {} 37 38 template <class MirrorType> 39 ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root) const 40 REQUIRES_SHARED(Locks::mutator_lock_) { 41 if (!root.IsNull()) { 42 VisitRoot(root); 43 } 44 } 45 46 template <class MirrorType> 47 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root) const 48 REQUIRES_SHARED(Locks::mutator_lock_) { 49 if (!root->IsNull()) { 50 VisitRoot(root); 51 } 52 } 53 54 template <class MirrorType> 55 void VisitRoot(GcRoot<MirrorType>& root) const REQUIRES_SHARED(Locks::mutator_lock_) { 56 VisitRoot(root.AddressWithoutBarrier()); 57 } 58 59 template <class MirrorType> 60 void VisitRoot(mirror::CompressedReference<MirrorType>* root) const 61 REQUIRES_SHARED(Locks::mutator_lock_) { 62 roots_.insert(root->AsMirrorPtr()); 63 } 64 65 mutable std::set<mirror::Object*> roots_; 66 }; 67 68 69 class ClassTableTest : public CommonRuntimeTest {}; 70 71 TEST_F(ClassTableTest, ClassTable) { 72 ScopedObjectAccess soa(Thread::Current()); 73 jobject jclass_loader = LoadDex("XandY"); 74 VariableSizedHandleScope hs(soa.Self()); 75 Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader))); 76 const char* descriptor_x = "LX;"; 77 const char* descriptor_y = "LY;"; 78 Handle<mirror::Class> h_X( 79 hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_x, class_loader))); 80 Handle<mirror::Class> h_Y( 81 hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_y, class_loader))); 82 Handle<mirror::Object> obj_X = hs.NewHandle(h_X->AllocObject(soa.Self())); 83 ASSERT_TRUE(obj_X != nullptr); 84 ClassTable table; 85 EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 0u); 86 EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 0u); 87 88 // Add h_X to the class table. 89 table.Insert(h_X.Get()); 90 EXPECT_EQ(table.LookupByDescriptor(h_X.Get()), h_X.Get()); 91 EXPECT_EQ(table.Lookup(descriptor_x, ComputeModifiedUtf8Hash(descriptor_x)), h_X.Get()); 92 EXPECT_EQ(table.Lookup("NOT_THERE", ComputeModifiedUtf8Hash("NOT_THERE")), nullptr); 93 EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 0u); 94 EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 1u); 95 96 // Create the zygote snapshot and ensure the accounting is correct. 97 table.FreezeSnapshot(); 98 EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 1u); 99 EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 0u); 100 101 // Test inserting and related lookup functions. 102 EXPECT_EQ(table.LookupByDescriptor(h_Y.Get()), nullptr); 103 EXPECT_FALSE(table.Contains(h_Y.Get())); 104 table.Insert(h_Y.Get()); 105 EXPECT_EQ(table.LookupByDescriptor(h_X.Get()), h_X.Get()); 106 EXPECT_EQ(table.LookupByDescriptor(h_Y.Get()), h_Y.Get()); 107 EXPECT_TRUE(table.Contains(h_X.Get())); 108 EXPECT_TRUE(table.Contains(h_Y.Get())); 109 110 EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 1u); 111 EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 1u); 112 113 // Test adding / clearing strong roots. 114 EXPECT_TRUE(table.InsertStrongRoot(obj_X.Get())); 115 EXPECT_FALSE(table.InsertStrongRoot(obj_X.Get())); 116 table.ClearStrongRoots(); 117 EXPECT_TRUE(table.InsertStrongRoot(obj_X.Get())); 118 119 // Collect all the roots and make sure there is nothing missing. 120 CollectRootVisitor roots; 121 table.VisitRoots(roots); 122 EXPECT_TRUE(roots.roots_.find(h_X.Get()) != roots.roots_.end()); 123 EXPECT_TRUE(roots.roots_.find(h_Y.Get()) != roots.roots_.end()); 124 EXPECT_TRUE(roots.roots_.find(obj_X.Get()) != roots.roots_.end()); 125 126 // Checks that vising only classes works. 127 std::set<mirror::Class*> classes; 128 table.Visit([&classes](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) { 129 classes.insert(klass.Ptr()); 130 return true; 131 }); 132 EXPECT_TRUE(classes.find(h_X.Get()) != classes.end()); 133 EXPECT_TRUE(classes.find(h_Y.Get()) != classes.end()); 134 EXPECT_EQ(classes.size(), 2u); 135 classes.clear(); 136 table.Visit([&classes](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) { 137 classes.insert(klass.Ptr()); 138 // Return false to exit the Visit early. 139 return false; 140 }); 141 EXPECT_EQ(classes.size(), 1u); 142 143 // Test remove. 144 table.Remove(descriptor_x); 145 EXPECT_FALSE(table.Contains(h_X.Get())); 146 147 // Test that WriteToMemory and ReadFromMemory work. 148 table.Insert(h_X.Get()); 149 const size_t count = table.WriteToMemory(nullptr); 150 std::unique_ptr<uint8_t[]> buffer(new uint8_t[count]()); 151 ASSERT_EQ(table.WriteToMemory(&buffer[0]), count); 152 ClassTable table2; 153 size_t count2 = table2.ReadFromMemory(&buffer[0]); 154 EXPECT_EQ(count, count2); 155 // Strong roots are not serialized, only classes. 156 EXPECT_TRUE(table2.Contains(h_X.Get())); 157 EXPECT_TRUE(table2.Contains(h_Y.Get())); 158 159 // TODO: Add tests for UpdateClass, InsertOatFile. 160 } 161 162 } // namespace mirror 163 } // namespace art 164