1 /* 2 * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "cds/aotClassLinker.hpp" 26 #include "cds/aotArtifactFinder.hpp" 27 #include "cds/aotClassInitializer.hpp" 28 #include "cds/dumpTimeClassInfo.inline.hpp" 29 #include "cds/heapShared.hpp" 30 #include "classfile/systemDictionaryShared.hpp" 31 #include "logging/log.hpp" 32 #include "memory/metaspaceClosure.hpp" 33 #include "oops/instanceKlass.hpp" 34 #include "oops/objArrayKlass.hpp" 35 #include "utilities/resourceHash.hpp" 36 37 // All the classes that should be included in the AOT cache (in at least the "allocated" state) 38 static GrowableArrayCHeap<Klass*, mtClassShared>* _all_cached_classes = nullptr; 39 40 // This is a stack that tracks all the AOT-inited classes that are waiting to be passed 41 // to HeapShared::copy_and_rescan_aot_inited_mirror(). 42 static GrowableArrayCHeap<InstanceKlass*, mtClassShared>* _pending_aot_inited_classes = nullptr; 43 44 static const int TABLE_SIZE = 15889; // prime number 45 using ClassesTable = ResourceHashtable<Klass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared>; 46 static ClassesTable* _seen_classes; // all classes that have been seen by AOTArtifactFinder 47 static ClassesTable* _aot_inited_classes; // all classes that need to be AOT-initialized. 48 49 void AOTArtifactFinder::initialize() { 50 _all_cached_classes = new GrowableArrayCHeap<Klass*, mtClassShared>(); 51 _pending_aot_inited_classes = new GrowableArrayCHeap<InstanceKlass*, mtClassShared>(); 52 _seen_classes = new (mtClass)ClassesTable(); 53 _aot_inited_classes = new (mtClass)ClassesTable(); 54 } 55 56 void AOTArtifactFinder::dispose() { 57 delete _all_cached_classes; 58 delete _seen_classes; 59 delete _aot_inited_classes; 60 delete _pending_aot_inited_classes; 61 _all_cached_classes = nullptr; 62 _seen_classes = nullptr; 63 _aot_inited_classes = nullptr; 64 _pending_aot_inited_classes = nullptr; 65 } 66 67 // Find all Klasses and oops that should be included in the AOT cache. See aotArtifactFinder.hpp 68 void AOTArtifactFinder::find_artifacts() { 69 // Some classes might have been marked as excluded as a side effect of running 70 // AOTConstantPoolResolver. Make sure we check all the remaining ones. 71 // 72 // Note, if a class is not excluded, it does NOT mean it will be automatically included 73 // into the AOT cache -- that will be decided by the code below. 74 SystemDictionaryShared::finish_exclusion_checks(); 75 76 start_scanning_for_oops(); 77 78 // Add the primitive array classes 79 for (int i = T_BOOLEAN; i < T_VOID+1; i++) { 80 BasicType bt = (BasicType)i; 81 if (is_java_primitive(bt)) { 82 add_cached_type_array_class(Universe::typeArrayKlass(bt)); 83 } 84 } 85 86 #if INCLUDE_CDS_JAVA_HEAP 87 // Add the mirrors that aren't associated with a Klass 88 // - primitive mirrors (E.g., "int.class" in Java code) 89 // - mirror of fillerArrayKlass 90 if (CDSConfig::is_dumping_heap()) { 91 for (int i = T_BOOLEAN; i < T_VOID+1; i++) { 92 BasicType bt = (BasicType)i; 93 if (!is_reference_type(bt)) { 94 oop orig_mirror = Universe::java_mirror(bt); 95 oop scratch_mirror = HeapShared::scratch_java_mirror(bt); 96 HeapShared::scan_java_mirror(orig_mirror); 97 log_trace(cds, heap, mirror)( 98 "Archived %s mirror object from " PTR_FORMAT, 99 type2name(bt), p2i(scratch_mirror)); 100 Universe::set_archived_basic_type_mirror_index(bt, HeapShared::append_root(scratch_mirror)); 101 } 102 } 103 104 // Universe::fillerArrayKlass() isn't in the class hierarchy, so handle it specially. 105 HeapShared::scan_java_mirror(Universe::fillerArrayKlass()->java_mirror()); 106 } 107 #endif 108 109 // Add all the InstanceKlasses (and their array classes) that are always included. 110 SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* ik, DumpTimeClassInfo& info) { 111 if (!info.is_excluded()) { 112 bool add = false; 113 if (!ik->is_hidden()) { 114 // All non-hidden classes are always included into the AOT cache 115 add = true; 116 } else { 117 if (!CDSConfig::is_dumping_invokedynamic()) { 118 // Legacy support of lambda proxies -- these are always included into the AOT cache 119 if (SystemDictionaryShared::is_registered_lambda_proxy_class(ik)) { 120 add = true; 121 } 122 } else { 123 assert(!SystemDictionaryShared::is_registered_lambda_proxy_class(ik), 124 "registered lambda proxies are only for legacy lambda proxy support"); 125 } 126 } 127 128 if (add) { 129 add_cached_instance_class(ik); 130 if (AOTClassInitializer::can_archive_initialized_mirror(ik)) { 131 add_aot_inited_class(ik); 132 } 133 } 134 } 135 }); 136 137 #if INCLUDE_CDS_JAVA_HEAP 138 // Keep scanning until we discover no more class that need to be AOT-initialized. 139 if (CDSConfig::is_initing_classes_at_dump_time()) { 140 while (_pending_aot_inited_classes->length() > 0) { 141 InstanceKlass* ik = _pending_aot_inited_classes->pop(); 142 HeapShared::copy_and_rescan_aot_inited_mirror(ik); 143 } 144 } 145 #endif 146 147 // Exclude all the (hidden) classes that have not been discovered by the code above. 148 SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* k, DumpTimeClassInfo& info) { 149 if (!info.is_excluded() && _seen_classes->get(k) == nullptr) { 150 info.set_excluded(); 151 assert(k->is_hidden(), "must be"); 152 if (log_is_enabled(Info, cds)) { 153 ResourceMark rm; 154 log_info(cds)("Skipping %s: Hidden class", k->name()->as_C_string()); 155 } 156 } 157 }); 158 159 end_scanning_for_oops(); 160 } 161 162 void AOTArtifactFinder::start_scanning_for_oops() { 163 #if INCLUDE_CDS_JAVA_HEAP 164 if (CDSConfig::is_dumping_heap()) { 165 HeapShared::start_scanning_for_oops(); 166 } 167 #endif 168 } 169 170 void AOTArtifactFinder::end_scanning_for_oops() { 171 #if INCLUDE_CDS_JAVA_HEAP 172 if (CDSConfig::is_dumping_heap()) { 173 HeapShared::end_scanning_for_oops(); 174 } 175 #endif 176 } 177 178 void AOTArtifactFinder::add_aot_inited_class(InstanceKlass* ik) { 179 if (CDSConfig::is_initing_classes_at_dump_time()) { 180 assert(ik->is_initialized(), "must be"); 181 add_cached_instance_class(ik); 182 183 bool created; 184 _aot_inited_classes->put_if_absent(ik, &created); 185 if (created) { 186 _pending_aot_inited_classes->push(ik); 187 188 InstanceKlass* s = ik->java_super(); 189 if (s != nullptr) { 190 add_aot_inited_class(s); 191 } 192 193 Array<InstanceKlass*>* interfaces = ik->local_interfaces(); 194 int len = interfaces->length(); 195 for (int i = 0; i < len; i++) { 196 InstanceKlass* intf = interfaces->at(i); 197 if (intf->is_initialized()) { 198 add_aot_inited_class(intf); 199 } 200 } 201 } 202 } 203 } 204 205 void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) { 206 bool created; 207 _seen_classes->put_if_absent(ik, &created); 208 if (created) { 209 _all_cached_classes->append(ik); 210 scan_oops_in_instance_class(ik); 211 if (ik->is_hidden() && CDSConfig::is_initing_classes_at_dump_time()) { 212 bool succeed = AOTClassLinker::try_add_candidate(ik); 213 guarantee(succeed, "All cached hidden classes must be aot-linkable"); 214 add_aot_inited_class(ik); 215 } 216 } 217 } 218 219 void AOTArtifactFinder::add_cached_type_array_class(TypeArrayKlass* tak) { 220 bool created; 221 _seen_classes->put_if_absent(tak, &created); 222 if (created) { 223 _all_cached_classes->append(tak); 224 scan_oops_in_array_class(tak); 225 } 226 } 227 228 void AOTArtifactFinder::add_cached_class(Klass* k) { 229 if (k->is_typeArray_klass()) { 230 add_cached_type_array_class(TypeArrayKlass::cast(k)); 231 } else if (k->is_objArray_klass()) { 232 add_cached_class(ObjArrayKlass::cast(k)->element_klass()); 233 } else { 234 add_cached_instance_class(InstanceKlass::cast(k)); 235 } 236 } 237 238 void AOTArtifactFinder::scan_oops_in_instance_class(InstanceKlass* ik) { 239 #if INCLUDE_CDS_JAVA_HEAP 240 if (CDSConfig::is_dumping_heap()) { 241 HeapShared::scan_java_class(ik); 242 scan_oops_in_array_class(ik->array_klasses()); 243 } 244 #endif 245 } 246 247 void AOTArtifactFinder::scan_oops_in_array_class(ArrayKlass* ak) { 248 #if INCLUDE_CDS_JAVA_HEAP 249 if (CDSConfig::is_dumping_heap()) { 250 while (ak != nullptr) { 251 HeapShared::scan_java_class(ak); 252 ak = ak->array_klass_or_null(); 253 } 254 } 255 #endif 256 } 257 258 void AOTArtifactFinder::all_cached_classes_do(MetaspaceClosure* it) { 259 for (int i = 0; i < _all_cached_classes->length(); i++) { 260 it->push(_all_cached_classes->adr_at(i)); 261 } 262 }