1 /* 2 * Copyright (c) 2021, 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 #ifndef SHARE_CDS_DUMPTIMECLASSINFO_HPP 26 #define SHARE_CDS_DUMPTIMECLASSINFO_HPP 27 28 #include "cds/aotMetaspace.hpp" 29 #include "cds/archiveBuilder.hpp" 30 #include "cds/archiveUtils.hpp" 31 #include "cds/cdsConfig.hpp" 32 #include "classfile/compactHashtable.hpp" 33 #include "memory/metaspaceClosure.hpp" 34 #include "oops/instanceKlass.hpp" 35 #include "prims/jvmtiExport.hpp" 36 #include "utilities/growableArray.hpp" 37 38 class Method; 39 class Symbol; 40 41 class DumpTimeClassInfo: public CHeapObj<mtClass> { 42 bool _excluded; 43 bool _is_aot_tooling_class; 44 bool _is_early_klass; 45 bool _has_checked_exclusion; 46 bool _can_be_preinited; 47 bool _has_done_preinit_check; 48 49 class DTLoaderConstraint { 50 Symbol* _name; 51 char _loader_type1; 52 char _loader_type2; 53 public: 54 DTLoaderConstraint() : _name(nullptr), _loader_type1('0'), _loader_type2('0') {} 55 DTLoaderConstraint(Symbol* name, char l1, char l2) : _name(name), _loader_type1(l1), _loader_type2(l2) { 56 Symbol::maybe_increment_refcount(_name); 57 } 58 DTLoaderConstraint(const DTLoaderConstraint& src) { 59 _name = src._name; 60 _loader_type1 = src._loader_type1; 61 _loader_type2 = src._loader_type2; 62 Symbol::maybe_increment_refcount(_name); 63 } 64 DTLoaderConstraint& operator=(DTLoaderConstraint src) { 65 swap(_name, src._name); // c++ copy-and-swap idiom 66 _loader_type1 = src._loader_type1; 67 _loader_type2 = src._loader_type2; 68 return *this; 69 } 70 ~DTLoaderConstraint() { 71 Symbol::maybe_decrement_refcount(_name); 72 } 73 74 bool equals(const DTLoaderConstraint& t) { 75 return t._name == _name && 76 ((t._loader_type1 == _loader_type1 && t._loader_type2 == _loader_type2) || 77 (t._loader_type2 == _loader_type1 && t._loader_type1 == _loader_type2)); 78 } 79 void metaspace_pointers_do(MetaspaceClosure* it) { 80 it->push(&_name); 81 } 82 83 Symbol* name() { return _name; } 84 char loader_type1() { return _loader_type1; } 85 char loader_type2() { return _loader_type2; } 86 }; 87 88 class DTVerifierConstraint { 89 Symbol* _name; 90 Symbol* _from_name; 91 public: 92 DTVerifierConstraint() : _name(nullptr), _from_name(nullptr) {} 93 DTVerifierConstraint(Symbol* n, Symbol* fn = nullptr) : _name(n), _from_name(fn) { 94 Symbol::maybe_increment_refcount(_name); 95 Symbol::maybe_increment_refcount(_from_name); 96 } 97 DTVerifierConstraint(const DTVerifierConstraint& src) { 98 _name = src._name; 99 _from_name = src._from_name; 100 Symbol::maybe_increment_refcount(_name); 101 Symbol::maybe_increment_refcount(_from_name); 102 } 103 DTVerifierConstraint& operator=(DTVerifierConstraint src) { 104 swap(_name, src._name); // c++ copy-and-swap idiom 105 swap(_from_name, src._from_name); // c++ copy-and-swap idiom 106 return *this; 107 } 108 ~DTVerifierConstraint() { 109 Symbol::maybe_decrement_refcount(_name); 110 Symbol::maybe_decrement_refcount(_from_name); 111 } 112 bool equals(Symbol* n, Symbol* fn) { 113 return (_name == n) && (_from_name == fn); 114 } 115 void metaspace_pointers_do(MetaspaceClosure* it) { 116 it->push(&_name); 117 it->push(&_from_name); 118 } 119 120 Symbol* name() { return _name; } 121 Symbol* from_name() { return _from_name; } 122 }; 123 124 public: 125 InstanceKlass* _klass; 126 InstanceKlass* _nest_host; 127 bool _failed_verification; 128 bool _is_registered_lambda_proxy; 129 int _id; 130 int _clsfile_size; 131 int _clsfile_crc32; 132 GrowableArray<DTVerifierConstraint>* _verifier_constraints; 133 GrowableArray<char>* _verifier_constraint_flags; 134 GrowableArray<DTLoaderConstraint>* _loader_constraints; 135 GrowableArray<int>* _enum_klass_static_fields; 136 137 DumpTimeClassInfo() { 138 _klass = nullptr; 139 _nest_host = nullptr; 140 _failed_verification = false; 141 _is_registered_lambda_proxy = false; 142 _has_checked_exclusion = false; 143 _can_be_preinited = false; 144 _has_done_preinit_check = false; 145 _id = -1; 146 _clsfile_size = -1; 147 _clsfile_crc32 = -1; 148 _excluded = false; 149 _is_aot_tooling_class = false; 150 _is_early_klass = JvmtiExport::is_early_phase(); 151 _verifier_constraints = nullptr; 152 _verifier_constraint_flags = nullptr; 153 _loader_constraints = nullptr; 154 _enum_klass_static_fields = nullptr; 155 } 156 DumpTimeClassInfo& operator=(const DumpTimeClassInfo&) = delete; 157 ~DumpTimeClassInfo(); 158 159 // For old verifier: only name is saved; all other fields are null/false. 160 void add_verification_constraint(Symbol* name, 161 Symbol* from_name = nullptr, bool from_field_is_protected = false, bool from_is_array = false, bool from_is_object = false); 162 void record_linking_constraint(Symbol* name, Handle loader1, Handle loader2); 163 void add_enum_klass_static_field(int archived_heap_root_index); 164 int enum_klass_static_field(int which_field); 165 bool is_builtin(); 166 167 private: 168 template <typename T> 169 static int array_length_or_zero(GrowableArray<T>* array) { 170 if (array == nullptr) { 171 return 0; 172 } else { 173 return array->length(); 174 } 175 } 176 177 public: 178 179 int num_verifier_constraints() const { 180 return array_length_or_zero(_verifier_constraint_flags); 181 } 182 183 Symbol* verifier_constraint_name_at(int i) const { 184 return _verifier_constraints->at(i).name(); 185 } 186 187 Symbol* verifier_constraint_from_name_at(int i) const { 188 return _verifier_constraints->at(i).from_name(); 189 } 190 191 int num_loader_constraints() const { 192 return array_length_or_zero(_loader_constraints); 193 } 194 195 int num_enum_klass_static_fields() const { 196 return array_length_or_zero(_enum_klass_static_fields); 197 } 198 199 void metaspace_pointers_do(MetaspaceClosure* it) { 200 it->push(&_klass); 201 it->push(&_nest_host); 202 if (_verifier_constraints != nullptr) { 203 for (int i = 0; i < _verifier_constraints->length(); i++) { 204 _verifier_constraints->adr_at(i)->metaspace_pointers_do(it); 205 } 206 } 207 if (_loader_constraints != nullptr) { 208 for (int i = 0; i < _loader_constraints->length(); i++) { 209 _loader_constraints->adr_at(i)->metaspace_pointers_do(it); 210 } 211 } 212 } 213 214 bool is_excluded() { 215 return _excluded || _failed_verification; 216 } 217 218 bool is_aot_tooling_class() { 219 return _is_aot_tooling_class; 220 } 221 222 void set_is_aot_tooling_class() { 223 _is_aot_tooling_class = true; 224 } 225 226 // Was this class loaded while JvmtiExport::is_early_phase()==true 227 bool is_early_klass() { 228 return _is_early_klass; 229 } 230 231 // simple accessors 232 void set_excluded() { _excluded = true; } 233 bool has_checked_exclusion() const { return _has_checked_exclusion; } 234 void set_has_checked_exclusion() { _has_checked_exclusion = true; } 235 bool failed_verification() const { return _failed_verification; } 236 void set_failed_verification() { _failed_verification = true; } 237 InstanceKlass* nest_host() const { return _nest_host; } 238 void set_nest_host(InstanceKlass* nest_host) { _nest_host = nest_host; } 239 240 bool can_be_preinited() const { return _can_be_preinited; } 241 bool has_done_preinit_check() const { return _has_done_preinit_check; } 242 243 void set_can_be_preinited(bool v) { 244 _can_be_preinited = v; 245 _has_done_preinit_check = true; 246 } 247 void reset_preinit_check() { 248 _can_be_preinited = false; 249 _has_done_preinit_check = false; 250 } 251 252 size_t runtime_info_bytesize() const; 253 }; 254 255 template <typename T> 256 inline unsigned DumpTimeSharedClassTable_hash(T* const& k) { 257 if (CDSConfig::is_dumping_static_archive()) { 258 // Deterministic archive contents 259 uintx delta = k->name() - AOTMetaspace::symbol_rs_base(); 260 return primitive_hash<uintx>(delta); 261 } else { 262 // Deterministic archive is not possible because classes can be loaded 263 // in multiple threads. 264 return primitive_hash<T*>(k); 265 } 266 } 267 268 using DumpTimeSharedClassTableBaseType = HashTable< 269 InstanceKlass*, 270 DumpTimeClassInfo, 271 15889, // prime number 272 AnyObj::C_HEAP, 273 mtClassShared, 274 &DumpTimeSharedClassTable_hash>; 275 276 class DumpTimeSharedClassTable: public DumpTimeSharedClassTableBaseType 277 { 278 int _builtin_count; 279 int _unregistered_count; 280 public: 281 DumpTimeSharedClassTable() { 282 _builtin_count = 0; 283 _unregistered_count = 0; 284 } 285 DumpTimeClassInfo* allocate_info(InstanceKlass* k); 286 DumpTimeClassInfo* get_info(InstanceKlass* k); 287 void inc_builtin_count() { _builtin_count++; } 288 void inc_unregistered_count() { _unregistered_count++; } 289 void update_counts(); 290 int count_of(bool is_builtin) const { 291 if (is_builtin) { 292 return _builtin_count; 293 } else { 294 return _unregistered_count; 295 } 296 } 297 298 template<class ITER> void iterate_all_live_classes(ITER* iter) const; 299 template<typename Function> void iterate_all_live_classes(Function function) const; 300 template<typename Function> void iterate_all_classes_in_builtin_loaders(Function function) const; 301 302 private: 303 // It's unsafe to iterate on classes whose loader is dead. 304 // Declare these private and don't implement them. This forces users of 305 // DumpTimeSharedClassTable to use the iterate_all_live_classes() methods 306 // instead. 307 template<class ITER> void iterate(ITER* iter) const; 308 template<typename Function> void iterate(Function function) const; 309 template<typename Function> void iterate_all(Function function) const; 310 }; 311 312 #endif // SHARE_CDS_DUMPTIMECLASSINFO_HPP