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