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