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/aotReferenceObjSupport.hpp" 29 #include "cds/dumpTimeClassInfo.inline.hpp" 30 #include "cds/heapShared.hpp" 31 #include "cds/lambdaProxyClassDictionary.hpp" 32 #include "classfile/systemDictionaryShared.hpp" 33 #include "logging/log.hpp" 34 #include "memory/metaspaceClosure.hpp" 35 #include "oops/instanceKlass.hpp" 36 #include "oops/objArrayKlass.hpp" 37 #include "oops/trainingData.hpp" 38 #include "utilities/resourceHash.hpp" 39 40 // All the classes that should be included in the AOT cache (in at least the "allocated" state) 41 static GrowableArrayCHeap<Klass*, mtClassShared>* _all_cached_classes = nullptr; 42 43 // This is a stack that tracks all the AOT-inited classes that are waiting to be passed 44 // to HeapShared::copy_and_rescan_aot_inited_mirror(). 45 static GrowableArrayCHeap<InstanceKlass*, mtClassShared>* _pending_aot_inited_classes = nullptr; 46 47 static const int TABLE_SIZE = 15889; // prime number 48 using ClassesTable = ResourceHashtable<Klass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared>; 49 static ClassesTable* _seen_classes; // all classes that have been seen by AOTArtifactFinder 50 static ClassesTable* _aot_inited_classes; // all classes that need to be AOT-initialized. 51 52 void AOTArtifactFinder::initialize() { 53 _all_cached_classes = new GrowableArrayCHeap<Klass*, mtClassShared>(); 54 _pending_aot_inited_classes = new GrowableArrayCHeap<InstanceKlass*, mtClassShared>(); 55 _seen_classes = new (mtClass)ClassesTable(); 56 _aot_inited_classes = new (mtClass)ClassesTable(); 57 } 58 59 void AOTArtifactFinder::dispose() { 60 delete _all_cached_classes; 61 delete _seen_classes; 62 delete _aot_inited_classes; 63 delete _pending_aot_inited_classes; 64 _all_cached_classes = nullptr; 65 _seen_classes = nullptr; 66 _aot_inited_classes = nullptr; 67 _pending_aot_inited_classes = nullptr; 68 } 69 70 // Find all Klasses and oops that should be included in the AOT cache. See aotArtifactFinder.hpp 71 void AOTArtifactFinder::find_artifacts() { 72 // Some classes might have been marked as excluded as a side effect of running 73 // AOTConstantPoolResolver. Make sure we check all the remaining ones. 74 // 75 // Note, if a class is not excluded, it does NOT mean it will be automatically included 76 // into the AOT cache -- that will be decided by the code below. 77 SystemDictionaryShared::finish_exclusion_checks(); 78 AOTReferenceObjSupport::init_keep_alive_objs_table(); 79 80 start_scanning_for_oops(); 81 82 // Add the primitive array classes 83 for (int i = T_BOOLEAN; i < T_VOID+1; i++) { 84 BasicType bt = (BasicType)i; 85 if (is_java_primitive(bt)) { 86 add_cached_type_array_class(Universe::typeArrayKlass(bt)); 87 } 88 } 89 90 #if INCLUDE_CDS_JAVA_HEAP 91 // Add the mirrors that aren't associated with a Klass 92 // - primitive mirrors (E.g., "int.class" in Java code) 93 // - mirror of fillerArrayKlass 94 if (CDSConfig::is_dumping_heap()) { 95 for (int i = T_BOOLEAN; i < T_VOID+1; i++) { 96 BasicType bt = (BasicType)i; 97 if (!is_reference_type(bt)) { 98 oop orig_mirror = Universe::java_mirror(bt); 99 oop scratch_mirror = HeapShared::scratch_java_mirror(bt); 100 HeapShared::scan_java_mirror(orig_mirror); 101 log_trace(cds, heap, mirror)( 102 "Archived %s mirror object from " PTR_FORMAT, 103 type2name(bt), p2i(scratch_mirror)); 104 Universe::set_archived_basic_type_mirror_index(bt, HeapShared::append_root(scratch_mirror)); 105 } 106 } 107 108 // Universe::fillerArrayKlass() isn't in the class hierarchy, so handle it specially. 109 HeapShared::scan_java_mirror(Universe::fillerArrayKlass()->java_mirror()); 110 } 111 #endif 112 113 // Add all the InstanceKlasses (and their array classes) that are always included. 114 SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* ik, DumpTimeClassInfo& info) { 115 // Skip "AOT tooling classes" in this block. They will be included in the AOT cache only if 116 // - One of their subtypes is included 117 // - One of their instances is found by HeapShared. 118 if (!info.is_excluded() && !info.is_aot_tooling_class()) { 119 bool add = false; 120 if (!ik->is_hidden()) { 121 // All non-hidden classes are always included into the AOT cache 122 add = true; 123 } else { 124 if (CDSConfig::is_dumping_lambdas_in_legacy_mode()) { 125 // Legacy support of lambda proxies -- these are always included into the AOT cache 126 if (LambdaProxyClassDictionary::is_registered_lambda_proxy_class(ik)) { 127 add = true; 128 } 129 } else { 130 assert(!LambdaProxyClassDictionary::is_registered_lambda_proxy_class(ik), 131 "registered lambda proxies are only for legacy lambda proxy support"); 132 } 133 } 134 135 if (add) { 136 add_cached_instance_class(ik); 137 if (AOTClassInitializer::can_archive_initialized_mirror(ik)) { 138 add_aot_inited_class(ik); 139 } 140 } 141 } 142 }); 143 144 #if INCLUDE_CDS_JAVA_HEAP 145 // Keep scanning until we discover no more class that need to be AOT-initialized. 146 if (CDSConfig::is_initing_classes_at_dump_time()) { 147 while (_pending_aot_inited_classes->length() > 0) { 148 InstanceKlass* ik = _pending_aot_inited_classes->pop(); 149 HeapShared::copy_and_rescan_aot_inited_mirror(ik); 150 } 151 } 152 #endif 153 154 // Exclude all the (hidden) classes that have not been discovered by the code above. 155 SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* k, DumpTimeClassInfo& info) { 156 if (!info.is_excluded() && _seen_classes->get(k) == nullptr) { 157 info.set_excluded(); 158 info.set_has_checked_exclusion(); 159 if (log_is_enabled(Debug, cds)) { 160 ResourceMark rm; 161 log_debug(cds)("Skipping %s: %s class", k->name()->as_C_string(), 162 k->is_hidden() ? "Unreferenced hidden" : "AOT tooling"); 163 } 164 } 165 }); 166 167 end_scanning_for_oops(); 168 169 TrainingData::cleanup_training_data(); 170 } 171 172 void AOTArtifactFinder::start_scanning_for_oops() { 173 #if INCLUDE_CDS_JAVA_HEAP 174 if (CDSConfig::is_dumping_heap()) { 175 HeapShared::start_scanning_for_oops(); 176 } 177 #endif 178 } 179 180 void AOTArtifactFinder::end_scanning_for_oops() { 181 #if INCLUDE_CDS_JAVA_HEAP 182 if (CDSConfig::is_dumping_heap()) { 183 HeapShared::end_scanning_for_oops(); 184 } 185 #endif 186 } 187 188 void AOTArtifactFinder::add_aot_inited_class(InstanceKlass* ik) { 189 if (CDSConfig::is_initing_classes_at_dump_time()) { 190 assert(ik->is_initialized(), "must be"); 191 add_cached_instance_class(ik); 192 193 bool created; 194 _aot_inited_classes->put_if_absent(ik, &created); 195 if (created) { 196 _pending_aot_inited_classes->push(ik); 197 198 InstanceKlass* s = ik->java_super(); 199 if (s != nullptr) { 200 add_aot_inited_class(s); 201 } 202 203 Array<InstanceKlass*>* interfaces = ik->local_interfaces(); 204 int len = interfaces->length(); 205 for (int i = 0; i < len; i++) { 206 InstanceKlass* intf = interfaces->at(i); 207 if (intf->is_initialized()) { 208 add_aot_inited_class(intf); 209 } 210 } 211 } 212 } 213 } 214 215 void AOTArtifactFinder::append_to_all_cached_classes(Klass* k) { 216 precond(!SystemDictionaryShared::should_be_excluded(k)); 217 _all_cached_classes->append(k); 218 } 219 220 void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) { 221 if (CDSConfig::is_dumping_dynamic_archive() && ik->is_shared()) { 222 // This class is already included in the base archive. No need to cache 223 // it again in the dynamic archive. 224 return; 225 } 226 227 bool created; 228 _seen_classes->put_if_absent(ik, &created); 229 if (created) { 230 append_to_all_cached_classes(ik); 231 232 // All super types must be added. 233 InstanceKlass* s = ik->java_super(); 234 if (s != nullptr) { 235 add_cached_instance_class(s); 236 } 237 238 Array<InstanceKlass*>* interfaces = ik->local_interfaces(); 239 int len = interfaces->length(); 240 for (int i = 0; i < len; i++) { 241 InstanceKlass* intf = interfaces->at(i); 242 add_cached_instance_class(intf); 243 } 244 245 if (CDSConfig::is_dumping_final_static_archive() && ik->is_shared_unregistered_class()) { 246 // The following are not appliable to unregistered classes 247 return; 248 } 249 scan_oops_in_instance_class(ik); 250 if (ik->is_hidden() && CDSConfig::is_initing_classes_at_dump_time()) { 251 bool succeed = AOTClassLinker::try_add_candidate(ik); 252 guarantee(succeed, "All cached hidden classes must be aot-linkable"); 253 add_aot_inited_class(ik); 254 } 255 } 256 } 257 258 void AOTArtifactFinder::add_cached_type_array_class(TypeArrayKlass* tak) { 259 bool created; 260 _seen_classes->put_if_absent(tak, &created); 261 if (created) { 262 append_to_all_cached_classes(tak); 263 scan_oops_in_array_class(tak); 264 } 265 } 266 267 void AOTArtifactFinder::add_cached_class(Klass* k) { 268 if (k->is_typeArray_klass()) { 269 add_cached_type_array_class(TypeArrayKlass::cast(k)); 270 } else if (k->is_objArray_klass()) { 271 add_cached_class(ObjArrayKlass::cast(k)->element_klass()); 272 } else { 273 add_cached_instance_class(InstanceKlass::cast(k)); 274 } 275 } 276 277 void AOTArtifactFinder::scan_oops_in_instance_class(InstanceKlass* ik) { 278 #if INCLUDE_CDS_JAVA_HEAP 279 if (CDSConfig::is_dumping_heap()) { 280 HeapShared::scan_java_class(ik); 281 scan_oops_in_array_class(ik->array_klasses()); 282 } 283 #endif 284 } 285 286 void AOTArtifactFinder::scan_oops_in_array_class(ArrayKlass* ak) { 287 #if INCLUDE_CDS_JAVA_HEAP 288 if (CDSConfig::is_dumping_heap()) { 289 while (ak != nullptr) { 290 HeapShared::scan_java_class(ak); 291 ak = ak->array_klass_or_null(); 292 } 293 } 294 #endif 295 } 296 297 void AOTArtifactFinder::all_cached_classes_do(MetaspaceClosure* it) { 298 for (int i = 0; i < _all_cached_classes->length(); i++) { 299 it->push(_all_cached_classes->adr_at(i)); 300 } 301 }