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