1 /*
2 * Copyright (c) 2016, 2018, 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 "precompiled.hpp"
26 #include "classfile/classLoaderDataGraph.hpp"
27 #include "classfile/javaClasses.inline.hpp"
28 #include "classfile/moduleEntry.hpp"
29 #include "classfile/packageEntry.hpp"
30 #include "classfile/symbolTable.hpp"
31 #include "classfile/systemDictionary.hpp"
32 #include "jfr/jfr.hpp"
33 #include "jfr/jni/jfrGetAllEventClasses.hpp"
34 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
35 #include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp"
36 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp"
37 #include "jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp"
38 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
39 #include "jfr/recorder/storage/jfrBuffer.hpp"
40 #include "jfr/utilities/jfrHashtable.hpp"
41 #include "jfr/utilities/jfrTypes.hpp"
42 #include "memory/iterator.hpp"
43 #include "memory/resourceArea.hpp"
44 #include "oops/instanceKlass.hpp"
45 #include "oops/objArrayKlass.hpp"
46 #include "oops/oop.inline.hpp"
47 #include "memory/resourceArea.hpp"
48 #include "utilities/accessFlags.hpp"
49
50 // incremented on each checkpoint
51 static u8 checkpoint_id = 0;
52
53 // creates a unique id by combining a checkpoint relative symbol id (2^24)
54 // with the current checkpoint id (2^40)
55 #define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id)))
56
57 typedef const Klass* KlassPtr;
58 typedef const PackageEntry* PkgPtr;
59 typedef const ModuleEntry* ModPtr;
60 typedef const ClassLoaderData* CldPtr;
61 typedef const Method* MethodPtr;
62 typedef const Symbol* SymbolPtr;
63 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
64 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
65
module_id(PkgPtr pkg)66 static traceid module_id(PkgPtr pkg) {
67 assert(pkg != NULL, "invariant");
68 ModPtr module_entry = pkg->module();
69 return module_entry != NULL && module_entry->is_named() ? TRACE_ID(module_entry) : 0;
70 }
71
package_id(KlassPtr klass)72 static traceid package_id(KlassPtr klass) {
73 assert(klass != NULL, "invariant");
74 PkgPtr pkg_entry = klass->package();
75 return pkg_entry == NULL ? 0 : TRACE_ID(pkg_entry);
76 }
77
cld_id(CldPtr cld)78 static traceid cld_id(CldPtr cld) {
79 assert(cld != NULL, "invariant");
80 return cld->is_unsafe_anonymous() ? 0 : TRACE_ID(cld);
81 }
82
tag_leakp_klass_artifacts(KlassPtr k,bool class_unload)83 static void tag_leakp_klass_artifacts(KlassPtr k, bool class_unload) {
84 assert(k != NULL, "invariant");
85 PkgPtr pkg = k->package();
86 if (pkg != NULL) {
87 tag_leakp_artifact(pkg, class_unload);
88 ModPtr module = pkg->module();
89 if (module != NULL) {
90 tag_leakp_artifact(module, class_unload);
91 }
92 }
93 CldPtr cld = k->class_loader_data();
94 assert(cld != NULL, "invariant");
95 if (!cld->is_unsafe_anonymous()) {
96 tag_leakp_artifact(cld, class_unload);
97 }
98 }
99
100 class TagLeakpKlassArtifact {
101 bool _class_unload;
102 public:
TagLeakpKlassArtifact(bool class_unload)103 TagLeakpKlassArtifact(bool class_unload) : _class_unload(class_unload) {}
operator ()(KlassPtr klass)104 bool operator()(KlassPtr klass) {
105 if (_class_unload) {
106 if (LEAKP_USED_THIS_EPOCH(klass)) {
107 tag_leakp_klass_artifacts(klass, _class_unload);
108 }
109 } else {
110 if (LEAKP_USED_PREV_EPOCH(klass)) {
111 tag_leakp_klass_artifacts(klass, _class_unload);
112 }
113 }
114 return true;
115 }
116 };
117
118 /*
119 * In C++03, functions used as template parameters must have external linkage;
120 * this restriction was removed in C++11. Change back to "static" and
121 * rename functions when C++11 becomes available.
122 *
123 * The weird naming is an effort to decrease the risk of name clashes.
124 */
125
write__artifact__klass(JfrCheckpointWriter * writer,JfrArtifactSet * artifacts,const void * k)126 int write__artifact__klass(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
127 assert(writer != NULL, "invariant");
128 assert(artifacts != NULL, "invariant");
129 assert(k != NULL, "invariant");
130 KlassPtr klass = (KlassPtr)k;
131 traceid pkg_id = 0;
132 KlassPtr theklass = klass;
133 if (theklass->is_objArray_klass()) {
134 const ObjArrayKlass* obj_arr_klass = ObjArrayKlass::cast(klass);
135 theklass = obj_arr_klass->bottom_klass();
136 }
137 if (theklass->is_instance_klass()) {
138 pkg_id = package_id(theklass);
139 } else {
140 assert(theklass->is_typeArray_klass(), "invariant");
141 }
142 const traceid symbol_id = artifacts->mark(klass);
143 assert(symbol_id > 0, "need to have an address for symbol!");
144 writer->write(TRACE_ID(klass));
145 writer->write(cld_id(klass->class_loader_data()));
146 writer->write((traceid)CREATE_SYMBOL_ID(symbol_id));
147 writer->write(pkg_id);
148 writer->write((s4)klass->access_flags().get_flags());
149 return 1;
150 }
151
152 typedef LeakPredicate<KlassPtr> LeakKlassPredicate;
153 typedef JfrPredicatedArtifactWriterImplHost<KlassPtr, LeakKlassPredicate, write__artifact__klass> LeakKlassWriterImpl;
154 typedef JfrArtifactWriterHost<LeakKlassWriterImpl, TYPE_CLASS> LeakKlassWriter;
155 typedef JfrArtifactWriterImplHost<KlassPtr, write__artifact__klass> KlassWriterImpl;
156 typedef JfrArtifactWriterHost<KlassWriterImpl, TYPE_CLASS> KlassWriter;
157
write__artifact__method(JfrCheckpointWriter * writer,JfrArtifactSet * artifacts,const void * m)158 int write__artifact__method(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) {
159 assert(writer != NULL, "invariant");
160 assert(artifacts != NULL, "invariant");
161 assert(m != NULL, "invariant");
162 MethodPtr method = (MethodPtr)m;
163 const traceid method_name_symbol_id = artifacts->mark(method->name());
164 assert(method_name_symbol_id > 0, "invariant");
165 const traceid method_sig_symbol_id = artifacts->mark(method->signature());
166 assert(method_sig_symbol_id > 0, "invariant");
167 KlassPtr klass = method->method_holder();
168 assert(klass != NULL, "invariant");
169 assert(METHOD_USED_ANY_EPOCH(klass), "invariant");
170 writer->write((u8)METHOD_ID(klass, method));
171 writer->write((u8)TRACE_ID(klass));
172 writer->write((u8)CREATE_SYMBOL_ID(method_name_symbol_id));
173 writer->write((u8)CREATE_SYMBOL_ID(method_sig_symbol_id));
174 writer->write((u2)method->access_flags().get_flags());
175 writer->write(const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0);
176 return 1;
177 }
178
179 typedef JfrArtifactWriterImplHost<MethodPtr, write__artifact__method> MethodWriterImplTarget;
180 typedef JfrArtifactWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl;
181
write__artifact__package(JfrCheckpointWriter * writer,JfrArtifactSet * artifacts,const void * p)182 int write__artifact__package(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* p) {
183 assert(writer != NULL, "invariant");
184 assert(artifacts != NULL, "invariant");
185 assert(p != NULL, "invariant");
186 PkgPtr pkg = (PkgPtr)p;
187 Symbol* const pkg_name = pkg->name();
188 const traceid package_name_symbol_id = pkg_name != NULL ? artifacts->mark(pkg_name) : 0;
189 assert(package_name_symbol_id > 0, "invariant");
190 writer->write((traceid)TRACE_ID(pkg));
191 writer->write((traceid)CREATE_SYMBOL_ID(package_name_symbol_id));
192 writer->write(module_id(pkg));
193 writer->write((bool)pkg->is_exported());
194 return 1;
195 }
196
197 typedef LeakPredicate<PkgPtr> LeakPackagePredicate;
_compare_pkg_ptr_(PkgPtr const & lhs,PkgPtr const & rhs)198 int _compare_pkg_ptr_(PkgPtr const& lhs, PkgPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
199 typedef UniquePredicate<PkgPtr, _compare_pkg_ptr_> PackagePredicate;
200 typedef JfrPredicatedArtifactWriterImplHost<PkgPtr, LeakPackagePredicate, write__artifact__package> LeakPackageWriterImpl;
201 typedef JfrPredicatedArtifactWriterImplHost<PkgPtr, PackagePredicate, write__artifact__package> PackageWriterImpl;
202 typedef JfrArtifactWriterHost<LeakPackageWriterImpl, TYPE_PACKAGE> LeakPackageWriter;
203 typedef JfrArtifactWriterHost<PackageWriterImpl, TYPE_PACKAGE> PackageWriter;
204
write__artifact__module(JfrCheckpointWriter * writer,JfrArtifactSet * artifacts,const void * m)205 int write__artifact__module(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) {
206 assert( m != NULL, "invariant");
207 ModPtr entry = (ModPtr)m;
208 Symbol* const module_name = entry->name();
209 const traceid module_name_symbol_id = module_name != NULL ? artifacts->mark(module_name) : 0;
210 Symbol* const module_version = entry->version();
211 const traceid module_version_symbol_id = module_version != NULL ? artifacts->mark(module_version) : 0;
212 Symbol* const module_location = entry->location();
213 const traceid module_location_symbol_id = module_location != NULL ? artifacts->mark(module_location) : 0;
214 writer->write((traceid)TRACE_ID(entry));
215 writer->write(module_name_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_name_symbol_id));
216 writer->write(module_version_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_version_symbol_id));
217 writer->write(module_location_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_location_symbol_id));
218 writer->write(cld_id(entry->loader_data()));
219 return 1;
220 }
221
222 typedef LeakPredicate<ModPtr> LeakModulePredicate;
_compare_mod_ptr_(ModPtr const & lhs,ModPtr const & rhs)223 int _compare_mod_ptr_(ModPtr const& lhs, ModPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
224 typedef UniquePredicate<ModPtr, _compare_mod_ptr_> ModulePredicate;
225 typedef JfrPredicatedArtifactWriterImplHost<ModPtr, LeakModulePredicate, write__artifact__module> LeakModuleWriterImpl;
226 typedef JfrPredicatedArtifactWriterImplHost<ModPtr, ModulePredicate, write__artifact__module> ModuleWriterImpl;
227 typedef JfrArtifactWriterHost<LeakModuleWriterImpl, TYPE_MODULE> LeakModuleWriter;
228 typedef JfrArtifactWriterHost<ModuleWriterImpl, TYPE_MODULE> ModuleWriter;
229
write__artifact__classloader(JfrCheckpointWriter * writer,JfrArtifactSet * artifacts,const void * c)230 int write__artifact__classloader(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* c) {
231 assert(c != NULL, "invariant");
232 CldPtr cld = (CldPtr)c;
233 assert(!cld->is_unsafe_anonymous(), "invariant");
234 const traceid cld_id = TRACE_ID(cld);
235 // class loader type
236 const Klass* class_loader_klass = cld->class_loader_klass();
237 if (class_loader_klass == NULL) {
238 // (primordial) boot class loader
239 writer->write(cld_id); // class loader instance id
240 writer->write((traceid)0); // class loader type id (absence of)
241 writer->write((traceid)CREATE_SYMBOL_ID(1)); // 1 maps to synthetic name -> "bootstrap"
242 } else {
243 Symbol* symbol_name = cld->name();
244 const traceid symbol_name_id = symbol_name != NULL ? artifacts->mark(symbol_name) : 0;
245 writer->write(cld_id); // class loader instance id
246 writer->write(TRACE_ID(class_loader_klass)); // class loader type id
247 writer->write(symbol_name_id == 0 ? (traceid)0 :
248 (traceid)CREATE_SYMBOL_ID(symbol_name_id)); // class loader instance name
249 }
250 return 1;
251 }
252
253 typedef LeakPredicate<CldPtr> LeakCldPredicate;
_compare_cld_ptr_(CldPtr const & lhs,CldPtr const & rhs)254 int _compare_cld_ptr_(CldPtr const& lhs, CldPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
255 typedef UniquePredicate<CldPtr, _compare_cld_ptr_> CldPredicate;
256 typedef JfrPredicatedArtifactWriterImplHost<CldPtr, LeakCldPredicate, write__artifact__classloader> LeakCldWriterImpl;
257 typedef JfrPredicatedArtifactWriterImplHost<CldPtr, CldPredicate, write__artifact__classloader> CldWriterImpl;
258 typedef JfrArtifactWriterHost<LeakCldWriterImpl, TYPE_CLASSLOADER> LeakCldWriter;
259 typedef JfrArtifactWriterHost<CldWriterImpl, TYPE_CLASSLOADER> CldWriter;
260
261 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
262
write__artifact__symbol__entry__(JfrCheckpointWriter * writer,SymbolEntryPtr entry)263 static int write__artifact__symbol__entry__(JfrCheckpointWriter* writer,
264 SymbolEntryPtr entry) {
265 assert(writer != NULL, "invariant");
266 assert(entry != NULL, "invariant");
267 ResourceMark rm;
268 writer->write(CREATE_SYMBOL_ID(entry->id()));
269 writer->write(entry->value()->as_C_string());
270 return 1;
271 }
272
write__artifact__symbol__entry(JfrCheckpointWriter * writer,JfrArtifactSet * artifacts,const void * e)273 int write__artifact__symbol__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
274 assert(e != NULL, "invariant");
275 return write__artifact__symbol__entry__(writer, (SymbolEntryPtr)e);
276 }
277
278 typedef JfrArtifactWriterImplHost<SymbolEntryPtr, write__artifact__symbol__entry> SymbolEntryWriterImpl;
279 typedef JfrArtifactWriterHost<SymbolEntryWriterImpl, TYPE_SYMBOL> SymbolEntryWriter;
280
281 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
282
write__artifact__cstring__entry__(JfrCheckpointWriter * writer,CStringEntryPtr entry)283 static int write__artifact__cstring__entry__(JfrCheckpointWriter* writer, CStringEntryPtr entry) {
284 assert(writer != NULL, "invariant");
285 assert(entry != NULL, "invariant");
286 writer->write(CREATE_SYMBOL_ID(entry->id()));
287 writer->write(entry->value());
288 return 1;
289 }
290
write__artifact__cstring__entry(JfrCheckpointWriter * writer,JfrArtifactSet * artifacts,const void * e)291 int write__artifact__cstring__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
292 assert(e != NULL, "invariant");
293 return write__artifact__cstring__entry__(writer, (CStringEntryPtr)e);
294 }
295
296 typedef JfrArtifactWriterImplHost<CStringEntryPtr, write__artifact__cstring__entry> CStringEntryWriterImpl;
297 typedef JfrArtifactWriterHost<CStringEntryWriterImpl, TYPE_SYMBOL> CStringEntryWriter;
298
write__artifact__klass__symbol(JfrCheckpointWriter * writer,JfrArtifactSet * artifacts,const void * k)299 int write__artifact__klass__symbol(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
300 assert(writer != NULL, "invariant");
301 assert(artifacts != NULL, "invaiant");
302 assert(k != NULL, "invariant");
303 const InstanceKlass* const ik = (const InstanceKlass*)k;
304 if (ik->is_unsafe_anonymous()) {
305 CStringEntryPtr entry =
306 artifacts->map_cstring(JfrSymbolId::unsafe_anonymous_klass_name_hash_code(ik));
307 assert(entry != NULL, "invariant");
308 return write__artifact__cstring__entry__(writer, entry);
309 }
310
311 SymbolEntryPtr entry = artifacts->map_symbol(JfrSymbolId::regular_klass_name_hash_code(ik));
312 return write__artifact__symbol__entry__(writer, entry);
313 }
314
_compare_traceid_(const traceid & lhs,const traceid & rhs)315 int _compare_traceid_(const traceid& lhs, const traceid& rhs) {
316 return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
317 }
318
319 template <template <typename> class Predicate>
320 class KlassSymbolWriterImpl {
321 private:
322 JfrCheckpointWriter* _writer;
323 JfrArtifactSet* _artifacts;
324 Predicate<KlassPtr> _predicate;
325 MethodUsedPredicate<true> _method_used_predicate;
326 MethodFlagPredicate _method_flag_predicate;
327 UniquePredicate<traceid, _compare_traceid_> _unique_predicate;
328
329 int klass_symbols(KlassPtr klass);
330 int package_symbols(PkgPtr pkg);
331 int module_symbols(ModPtr module);
332 int class_loader_symbols(CldPtr cld);
333 int method_symbols(KlassPtr klass);
334
335 public:
336 typedef KlassPtr Type;
KlassSymbolWriterImpl(JfrCheckpointWriter * writer,JfrArtifactSet * artifacts,bool class_unload)337 KlassSymbolWriterImpl(JfrCheckpointWriter* writer,
338 JfrArtifactSet* artifacts,
339 bool class_unload) : _writer(writer),
340 _artifacts(artifacts),
341 _predicate(class_unload),
342 _method_used_predicate(class_unload),
343 _method_flag_predicate(class_unload),
344 _unique_predicate(class_unload) {}
345
operator ()(KlassPtr klass)346 int operator()(KlassPtr klass) {
347 assert(klass != NULL, "invariant");
348 int count = 0;
349 if (_predicate(klass)) {
350 count += klass_symbols(klass);
351 PkgPtr pkg = klass->package();
352 if (pkg != NULL) {
353 count += package_symbols(pkg);
354 ModPtr module = pkg->module();
355 if (module != NULL && module->is_named()) {
356 count += module_symbols(module);
357 }
358 }
359 CldPtr cld = klass->class_loader_data();
360 assert(cld != NULL, "invariant");
361 if (!cld->is_unsafe_anonymous()) {
362 count += class_loader_symbols(cld);
363 }
364 if (_method_used_predicate(klass)) {
365 count += method_symbols(klass);
366 }
367 }
368 return count;
369 }
370 };
371
372 template <template <typename> class Predicate>
klass_symbols(KlassPtr klass)373 int KlassSymbolWriterImpl<Predicate>::klass_symbols(KlassPtr klass) {
374 assert(klass != NULL, "invariant");
375 assert(_predicate(klass), "invariant");
376 const InstanceKlass* const ik = (const InstanceKlass*)klass;
377 if (ik->is_unsafe_anonymous()) {
378 CStringEntryPtr entry =
379 this->_artifacts->map_cstring(JfrSymbolId::unsafe_anonymous_klass_name_hash_code(ik));
380 assert(entry != NULL, "invariant");
381 return _unique_predicate(entry->id()) ? write__artifact__cstring__entry__(this->_writer, entry) : 0;
382 }
383 SymbolEntryPtr entry = this->_artifacts->map_symbol(ik->name());
384 assert(entry != NULL, "invariant");
385 return _unique_predicate(entry->id()) ? write__artifact__symbol__entry__(this->_writer, entry) : 0;
386 }
387
388 template <template <typename> class Predicate>
package_symbols(PkgPtr pkg)389 int KlassSymbolWriterImpl<Predicate>::package_symbols(PkgPtr pkg) {
390 assert(pkg != NULL, "invariant");
391 SymbolPtr pkg_name = pkg->name();
392 assert(pkg_name != NULL, "invariant");
393 SymbolEntryPtr package_symbol = this->_artifacts->map_symbol(pkg_name);
394 assert(package_symbol != NULL, "invariant");
395 return _unique_predicate(package_symbol->id()) ?
396 write__artifact__symbol__entry__(this->_writer, package_symbol) : 0;
397 }
398
399 template <template <typename> class Predicate>
module_symbols(ModPtr module)400 int KlassSymbolWriterImpl<Predicate>::module_symbols(ModPtr module) {
401 assert(module != NULL, "invariant");
402 assert(module->is_named(), "invariant");
403 int count = 0;
404 SymbolPtr sym = module->name();
405 SymbolEntryPtr entry = NULL;
406 if (sym != NULL) {
407 entry = this->_artifacts->map_symbol(sym);
408 assert(entry != NULL, "invariant");
409 if (_unique_predicate(entry->id())) {
410 count += write__artifact__symbol__entry__(this->_writer, entry);
411 }
412 }
413 sym = module->version();
414 if (sym != NULL) {
415 entry = this->_artifacts->map_symbol(sym);
416 assert(entry != NULL, "invariant");
417 if (_unique_predicate(entry->id())) {
418 count += write__artifact__symbol__entry__(this->_writer, entry);
419 }
420 }
421 sym = module->location();
422 if (sym != NULL) {
423 entry = this->_artifacts->map_symbol(sym);
424 assert(entry != NULL, "invariant");
425 if (_unique_predicate(entry->id())) {
426 count += write__artifact__symbol__entry__(this->_writer, entry);
427 }
428 }
429 return count;
430 }
431
432 template <template <typename> class Predicate>
class_loader_symbols(CldPtr cld)433 int KlassSymbolWriterImpl<Predicate>::class_loader_symbols(CldPtr cld) {
434 assert(cld != NULL, "invariant");
435 assert(!cld->is_unsafe_anonymous(), "invariant");
436 int count = 0;
437 // class loader type
438 const Klass* class_loader_klass = cld->class_loader_klass();
439 if (class_loader_klass == NULL) {
440 // (primordial) boot class loader
441 CStringEntryPtr entry = this->_artifacts->map_cstring(0);
442 assert(entry != NULL, "invariant");
443 assert(strncmp(entry->literal(),
444 BOOTSTRAP_LOADER_NAME,
445 BOOTSTRAP_LOADER_NAME_LEN) == 0, "invariant");
446 if (_unique_predicate(entry->id())) {
447 count += write__artifact__cstring__entry__(this->_writer, entry);
448 }
449 } else {
450 const Symbol* class_loader_name = cld->name();
451 if (class_loader_name != NULL) {
452 SymbolEntryPtr entry = this->_artifacts->map_symbol(class_loader_name);
453 assert(entry != NULL, "invariant");
454 if (_unique_predicate(entry->id())) {
455 count += write__artifact__symbol__entry__(this->_writer, entry);
456 }
457 }
458 }
459 return count;
460 }
461
462 template <template <typename> class Predicate>
method_symbols(KlassPtr klass)463 int KlassSymbolWriterImpl<Predicate>::method_symbols(KlassPtr klass) {
464 assert(_predicate(klass), "invariant");
465 assert(_method_used_predicate(klass), "invariant");
466 assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
467 int count = 0;
468 const InstanceKlass* const ik = InstanceKlass::cast(klass);
469 const int len = ik->methods()->length();
470 for (int i = 0; i < len; ++i) {
471 MethodPtr method = ik->methods()->at(i);
472 if (_method_flag_predicate(method)) {
473 SymbolEntryPtr entry = this->_artifacts->map_symbol(method->name());
474 assert(entry != NULL, "invariant");
475 if (_unique_predicate(entry->id())) {
476 count += write__artifact__symbol__entry__(this->_writer, entry);
477 }
478 entry = this->_artifacts->map_symbol(method->signature());
479 assert(entry != NULL, "invariant");
480 if (_unique_predicate(entry->id())) {
481 count += write__artifact__symbol__entry__(this->_writer, entry);
482 }
483 }
484 }
485 return count;
486 }
487
488 typedef KlassSymbolWriterImpl<LeakPredicate> LeakKlassSymbolWriterImpl;
489 typedef JfrArtifactWriterHost<LeakKlassSymbolWriterImpl, TYPE_SYMBOL> LeakKlassSymbolWriter;
490
491 class ClearKlassAndMethods {
492 private:
493 ClearArtifact<KlassPtr> _clear_klass_tag_bits;
494 ClearArtifact<MethodPtr> _clear_method_flag;
495 MethodUsedPredicate<false> _method_used_predicate;
496
497 public:
ClearKlassAndMethods(bool class_unload)498 ClearKlassAndMethods(bool class_unload) : _clear_klass_tag_bits(class_unload),
499 _clear_method_flag(class_unload),
500 _method_used_predicate(class_unload) {}
operator ()(KlassPtr klass)501 bool operator()(KlassPtr klass) {
502 if (_method_used_predicate(klass)) {
503 const InstanceKlass* ik = InstanceKlass::cast(klass);
504 const int len = ik->methods()->length();
505 for (int i = 0; i < len; ++i) {
506 MethodPtr method = ik->methods()->at(i);
507 _clear_method_flag(method);
508 }
509 }
510 _clear_klass_tag_bits(klass);
511 return true;
512 }
513 };
514
515 typedef CompositeFunctor<KlassPtr,
516 TagLeakpKlassArtifact,
517 LeakKlassWriter> LeakpKlassArtifactTagging;
518
519 typedef CompositeFunctor<KlassPtr,
520 LeakpKlassArtifactTagging,
521 KlassWriter> CompositeKlassWriter;
522
523 typedef CompositeFunctor<KlassPtr,
524 CompositeKlassWriter,
525 KlassArtifactRegistrator> CompositeKlassWriterRegistration;
526
527 typedef CompositeFunctor<KlassPtr,
528 KlassWriter,
529 KlassArtifactRegistrator> KlassWriterRegistration;
530
531 typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback;
532 typedef JfrArtifactCallbackHost<KlassPtr, CompositeKlassWriterRegistration> CompositeKlassCallback;
533
534 /*
535 * Composite operation
536 *
537 * TagLeakpKlassArtifact ->
538 * LeakpPredicate ->
539 * LeakpKlassWriter ->
540 * KlassPredicate ->
541 * KlassWriter ->
542 * KlassWriterRegistration
543 */
write_klass_constants(JfrCheckpointWriter * writer,JfrCheckpointWriter * leakp_writer)544 void JfrTypeSet::write_klass_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
545 assert(!_artifacts->has_klass_entries(), "invariant");
546 KlassArtifactRegistrator reg(_artifacts);
547 KlassWriter kw(writer, _artifacts, _class_unload);
548 KlassWriterRegistration kwr(&kw, ®);
549 if (leakp_writer == NULL) {
550 KlassCallback callback(&kwr);
551 _subsystem_callback = &callback;
552 do_klasses();
553 return;
554 }
555 TagLeakpKlassArtifact tagging(_class_unload);
556 LeakKlassWriter lkw(leakp_writer, _artifacts, _class_unload);
557 LeakpKlassArtifactTagging lpkat(&tagging, &lkw);
558 CompositeKlassWriter ckw(&lpkat, &kw);
559 CompositeKlassWriterRegistration ckwr(&ckw, ®);
560 CompositeKlassCallback callback(&ckwr);
561 _subsystem_callback = &callback;
562 do_klasses();
563 }
564
565 typedef CompositeFunctor<PkgPtr,
566 PackageWriter,
567 ClearArtifact<PkgPtr> > PackageWriterWithClear;
568
569 typedef CompositeFunctor<PkgPtr,
570 LeakPackageWriter,
571 PackageWriter> CompositePackageWriter;
572
573 typedef CompositeFunctor<PkgPtr,
574 CompositePackageWriter,
575 ClearArtifact<PkgPtr> > CompositePackageWriterWithClear;
576
577 class PackageFieldSelector {
578 public:
579 typedef PkgPtr TypePtr;
select(KlassPtr klass)580 static TypePtr select(KlassPtr klass) {
581 assert(klass != NULL, "invariant");
582 return ((InstanceKlass*)klass)->package();
583 }
584 };
585
586 typedef KlassToFieldEnvelope<PackageFieldSelector,
587 PackageWriterWithClear> KlassPackageWriterWithClear;
588
589 typedef KlassToFieldEnvelope<PackageFieldSelector,
590 CompositePackageWriterWithClear> KlassCompositePackageWriterWithClear;
591
592 typedef JfrArtifactCallbackHost<PkgPtr, PackageWriterWithClear> PackageCallback;
593 typedef JfrArtifactCallbackHost<PkgPtr, CompositePackageWriterWithClear> CompositePackageCallback;
594
595 /*
596 * Composite operation
597 *
598 * LeakpPackageWriter ->
599 * PackageWriter ->
600 * ClearArtifact<PackageEntry>
601 *
602 */
write_package_constants(JfrCheckpointWriter * writer,JfrCheckpointWriter * leakp_writer)603 void JfrTypeSet::write_package_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
604 assert(_artifacts->has_klass_entries(), "invariant");
605 ClearArtifact<PkgPtr> clear(_class_unload);
606 PackageWriter pw(writer, _artifacts, _class_unload);
607 if (leakp_writer == NULL) {
608 PackageWriterWithClear pwwc(&pw, &clear);
609 KlassPackageWriterWithClear kpwwc(&pwwc);
610 _artifacts->iterate_klasses(kpwwc);
611 PackageCallback callback(&pwwc);
612 _subsystem_callback = &callback;
613 do_packages();
614 return;
615 }
616 LeakPackageWriter lpw(leakp_writer, _artifacts, _class_unload);
617 CompositePackageWriter cpw(&lpw, &pw);
618 CompositePackageWriterWithClear cpwwc(&cpw, &clear);
619 KlassCompositePackageWriterWithClear ckpw(&cpwwc);
620 _artifacts->iterate_klasses(ckpw);
621 CompositePackageCallback callback(&cpwwc);
622 _subsystem_callback = &callback;
623 do_packages();
624 }
625
626 typedef CompositeFunctor<ModPtr,
627 ModuleWriter,
628 ClearArtifact<ModPtr> > ModuleWriterWithClear;
629
630 typedef CompositeFunctor<ModPtr,
631 LeakModuleWriter,
632 ModuleWriter> CompositeModuleWriter;
633
634 typedef CompositeFunctor<ModPtr,
635 CompositeModuleWriter,
636 ClearArtifact<ModPtr> > CompositeModuleWriterWithClear;
637
638 typedef JfrArtifactCallbackHost<ModPtr, ModuleWriterWithClear> ModuleCallback;
639 typedef JfrArtifactCallbackHost<ModPtr, CompositeModuleWriterWithClear> CompositeModuleCallback;
640
641 class ModuleFieldSelector {
642 public:
643 typedef ModPtr TypePtr;
select(KlassPtr klass)644 static TypePtr select(KlassPtr klass) {
645 assert(klass != NULL, "invariant");
646 PkgPtr pkg = klass->package();
647 return pkg != NULL ? pkg->module() : NULL;
648 }
649 };
650
651 typedef KlassToFieldEnvelope<ModuleFieldSelector,
652 ModuleWriterWithClear> KlassModuleWriterWithClear;
653
654 typedef KlassToFieldEnvelope<ModuleFieldSelector,
655 CompositeModuleWriterWithClear> KlassCompositeModuleWriterWithClear;
656
657 /*
658 * Composite operation
659 *
660 * LeakpModuleWriter ->
661 * ModuleWriter ->
662 * ClearArtifact<ModuleEntry>
663 */
write_module_constants(JfrCheckpointWriter * writer,JfrCheckpointWriter * leakp_writer)664 void JfrTypeSet::write_module_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
665 assert(_artifacts->has_klass_entries(), "invariant");
666 ClearArtifact<ModPtr> clear(_class_unload);
667 ModuleWriter mw(writer, _artifacts, _class_unload);
668 if (leakp_writer == NULL) {
669 ModuleWriterWithClear mwwc(&mw, &clear);
670 KlassModuleWriterWithClear kmwwc(&mwwc);
671 _artifacts->iterate_klasses(kmwwc);
672 ModuleCallback callback(&mwwc);
673 _subsystem_callback = &callback;
674 do_modules();
675 return;
676 }
677 LeakModuleWriter lmw(leakp_writer, _artifacts, _class_unload);
678 CompositeModuleWriter cmw(&lmw, &mw);
679 CompositeModuleWriterWithClear cmwwc(&cmw, &clear);
680 KlassCompositeModuleWriterWithClear kmwwc(&cmwwc);
681 _artifacts->iterate_klasses(kmwwc);
682 CompositeModuleCallback callback(&cmwwc);
683 _subsystem_callback = &callback;
684 do_modules();
685 }
686
687 typedef CompositeFunctor<CldPtr, CldWriter, ClearArtifact<CldPtr> > CldWriterWithClear;
688 typedef CompositeFunctor<CldPtr, LeakCldWriter, CldWriter> CompositeCldWriter;
689 typedef CompositeFunctor<CldPtr, CompositeCldWriter, ClearArtifact<CldPtr> > CompositeCldWriterWithClear;
690 typedef JfrArtifactCallbackHost<CldPtr, CldWriterWithClear> CldCallback;
691 typedef JfrArtifactCallbackHost<CldPtr, CompositeCldWriterWithClear> CompositeCldCallback;
692
693 class CldFieldSelector {
694 public:
695 typedef CldPtr TypePtr;
select(KlassPtr klass)696 static TypePtr select(KlassPtr klass) {
697 assert(klass != NULL, "invariant");
698 CldPtr cld = klass->class_loader_data();
699 return cld->is_unsafe_anonymous() ? NULL : cld;
700 }
701 };
702
703 typedef KlassToFieldEnvelope<CldFieldSelector, CldWriterWithClear> KlassCldWriterWithClear;
704 typedef KlassToFieldEnvelope<CldFieldSelector, CompositeCldWriterWithClear> KlassCompositeCldWriterWithClear;
705
706 /*
707 * Composite operation
708 *
709 * LeakpClassLoaderWriter ->
710 * ClassLoaderWriter ->
711 * ClearArtifact<ClassLoaderData>
712 */
write_class_loader_constants(JfrCheckpointWriter * writer,JfrCheckpointWriter * leakp_writer)713 void JfrTypeSet::write_class_loader_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
714 assert(_artifacts->has_klass_entries(), "invariant");
715 ClearArtifact<CldPtr> clear(_class_unload);
716 CldWriter cldw(writer, _artifacts, _class_unload);
717 if (leakp_writer == NULL) {
718 CldWriterWithClear cldwwc(&cldw, &clear);
719 KlassCldWriterWithClear kcldwwc(&cldwwc);
720 _artifacts->iterate_klasses(kcldwwc);
721 CldCallback callback(&cldwwc);
722 _subsystem_callback = &callback;
723 do_class_loaders();
724 return;
725 }
726 LeakCldWriter lcldw(leakp_writer, _artifacts, _class_unload);
727 CompositeCldWriter ccldw(&lcldw, &cldw);
728 CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
729 KlassCompositeCldWriterWithClear kcclwwc(&ccldwwc);
730 _artifacts->iterate_klasses(kcclwwc);
731 CompositeCldCallback callback(&ccldwwc);
732 _subsystem_callback = &callback;
733 do_class_loaders();
734 }
735
736 template <bool predicate_bool, typename MethodFunctor>
737 class MethodIteratorHost {
738 private:
739 MethodFunctor _method_functor;
740 MethodUsedPredicate<predicate_bool> _method_used_predicate;
741 MethodFlagPredicate _method_flag_predicate;
742
743 public:
MethodIteratorHost(JfrCheckpointWriter * writer,JfrArtifactSet * artifacts,bool class_unload,bool skip_header=false)744 MethodIteratorHost(JfrCheckpointWriter* writer,
745 JfrArtifactSet* artifacts,
746 bool class_unload,
747 bool skip_header = false) :
748 _method_functor(writer, artifacts, class_unload, skip_header),
749 _method_used_predicate(class_unload),
750 _method_flag_predicate(class_unload) {}
751
operator ()(KlassPtr klass)752 bool operator()(KlassPtr klass) {
753 if (_method_used_predicate(klass)) {
754 assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
755 const InstanceKlass* ik = InstanceKlass::cast(klass);
756 const int len = ik->methods()->length();
757 for (int i = 0; i < len; ++i) {
758 MethodPtr method = ik->methods()->at(i);
759 if (_method_flag_predicate(method)) {
760 _method_functor(method);
761 }
762 }
763 }
764 return true;
765 }
766
count() const767 int count() const { return _method_functor.count(); }
add(int count)768 void add(int count) { _method_functor.add(count); }
769 };
770
771 typedef MethodIteratorHost<true /*leakp */, MethodWriterImpl> LeakMethodWriter;
772 typedef MethodIteratorHost<false, MethodWriterImpl> MethodWriter;
773 typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
774
775 /*
776 * Composite operation
777 *
778 * LeakpMethodWriter ->
779 * MethodWriter
780 */
write_method_constants(JfrCheckpointWriter * writer,JfrCheckpointWriter * leakp_writer)781 void JfrTypeSet::write_method_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
782 assert(_artifacts->has_klass_entries(), "invariant");
783 MethodWriter mw(writer, _artifacts, _class_unload);
784 if (leakp_writer == NULL) {
785 _artifacts->iterate_klasses(mw);
786 return;
787 }
788 LeakMethodWriter lpmw(leakp_writer, _artifacts, _class_unload);
789 CompositeMethodWriter cmw(&lpmw, &mw);
790 _artifacts->iterate_klasses(cmw);
791 }
write_symbols_leakp(JfrCheckpointWriter * leakp_writer,JfrArtifactSet * artifacts,bool class_unload)792 static void write_symbols_leakp(JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
793 assert(leakp_writer != NULL, "invariant");
794 assert(artifacts != NULL, "invariant");
795 LeakKlassSymbolWriter lpksw(leakp_writer, artifacts, class_unload);
796 artifacts->iterate_klasses(lpksw);
797 }
write_symbols(JfrCheckpointWriter * writer,JfrCheckpointWriter * leakp_writer,JfrArtifactSet * artifacts,bool class_unload)798 static void write_symbols(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
799 assert(writer != NULL, "invariant");
800 assert(artifacts != NULL, "invariant");
801 if (leakp_writer != NULL) {
802 write_symbols_leakp(leakp_writer, artifacts, class_unload);
803 }
804 // iterate all registered symbols
805 SymbolEntryWriter symbol_writer(writer, artifacts, class_unload);
806 artifacts->iterate_symbols(symbol_writer);
807 CStringEntryWriter cstring_writer(writer, artifacts, class_unload, true); // skip header
808 artifacts->iterate_cstrings(cstring_writer);
809 symbol_writer.add(cstring_writer.count());
810 }
811
812 bool JfrTypeSet::_class_unload = false;
813 JfrArtifactSet* JfrTypeSet::_artifacts = NULL;
814 JfrArtifactClosure* JfrTypeSet::_subsystem_callback = NULL;
815
write_symbol_constants(JfrCheckpointWriter * writer,JfrCheckpointWriter * leakp_writer)816 void JfrTypeSet::write_symbol_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
817 assert(writer != NULL, "invariant");
818 assert(_artifacts->has_klass_entries(), "invariant");
819 write_symbols(writer, leakp_writer, _artifacts, _class_unload);
820 }
821
do_unloaded_klass(Klass * klass)822 void JfrTypeSet::do_unloaded_klass(Klass* klass) {
823 assert(klass != NULL, "invariant");
824 assert(_subsystem_callback != NULL, "invariant");
825 if (IS_JDK_JFR_EVENT_SUBKLASS(klass)) {
826 JfrEventClasses::increment_unloaded_event_class();
827 }
828 if (USED_THIS_EPOCH(klass)) { // includes leakp subset
829 _subsystem_callback->do_artifact(klass);
830 return;
831 }
832 if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
833 SET_LEAKP_USED_THIS_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
834 _subsystem_callback->do_artifact(klass);
835 }
836 }
837
do_klass(Klass * klass)838 void JfrTypeSet::do_klass(Klass* klass) {
839 assert(klass != NULL, "invariant");
840 assert(_subsystem_callback != NULL, "invariant");
841 if (USED_PREV_EPOCH(klass)) { // includes leakp subset
842 _subsystem_callback->do_artifact(klass);
843 return;
844 }
845 if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
846 SET_LEAKP_USED_PREV_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
847 _subsystem_callback->do_artifact(klass);
848 }
849 }
850
do_klasses()851 void JfrTypeSet::do_klasses() {
852 if (_class_unload) {
853 ClassLoaderDataGraph::classes_unloading_do(&do_unloaded_klass);
854 return;
855 }
856 ClassLoaderDataGraph::classes_do(&do_klass);
857 }
858
do_unloaded_package(PackageEntry * entry)859 void JfrTypeSet::do_unloaded_package(PackageEntry* entry) {
860 assert(entry != NULL, "invariant");
861 assert(_subsystem_callback != NULL, "invariant");
862 if (ANY_USED_THIS_EPOCH(entry)) { // includes leakp subset
863 _subsystem_callback->do_artifact(entry);
864 }
865 }
866
do_package(PackageEntry * entry)867 void JfrTypeSet::do_package(PackageEntry* entry) {
868 assert(_subsystem_callback != NULL, "invariant");
869 if (ANY_USED_PREV_EPOCH(entry)) { // includes leakp subset
870 _subsystem_callback->do_artifact(entry);
871 }
872 }
873
do_packages()874 void JfrTypeSet::do_packages() {
875 if (_class_unload) {
876 ClassLoaderDataGraph::packages_unloading_do(&do_unloaded_package);
877 return;
878 }
879 ClassLoaderDataGraph::packages_do(&do_package);
880 }
do_unloaded_module(ModuleEntry * entry)881 void JfrTypeSet::do_unloaded_module(ModuleEntry* entry) {
882 assert(entry != NULL, "invariant");
883 assert(_subsystem_callback != NULL, "invariant");
884 if (ANY_USED_THIS_EPOCH(entry)) { // includes leakp subset
885 _subsystem_callback->do_artifact(entry);
886 }
887 }
888
do_module(ModuleEntry * entry)889 void JfrTypeSet::do_module(ModuleEntry* entry) {
890 assert(_subsystem_callback != NULL, "invariant");
891 if (ANY_USED_PREV_EPOCH(entry)) { // includes leakp subset
892 _subsystem_callback->do_artifact(entry);
893 }
894 }
895
do_modules()896 void JfrTypeSet::do_modules() {
897 if (_class_unload) {
898 ClassLoaderDataGraph::modules_unloading_do(&do_unloaded_module);
899 return;
900 }
901 ClassLoaderDataGraph::modules_do(&do_module);
902 }
903
do_unloaded_class_loader_data(ClassLoaderData * cld)904 void JfrTypeSet::do_unloaded_class_loader_data(ClassLoaderData* cld) {
905 assert(_subsystem_callback != NULL, "invariant");
906 if (ANY_USED_THIS_EPOCH(cld)) { // includes leakp subset
907 _subsystem_callback->do_artifact(cld);
908 }
909 }
910
do_class_loader_data(ClassLoaderData * cld)911 void JfrTypeSet::do_class_loader_data(ClassLoaderData* cld) {
912 assert(_subsystem_callback != NULL, "invariant");
913 if (ANY_USED_PREV_EPOCH(cld)) { // includes leakp subset
914 _subsystem_callback->do_artifact(cld);
915 }
916 }
917
918 class CLDCallback : public CLDClosure {
919 private:
920 bool _class_unload;
921 public:
CLDCallback(bool class_unload)922 CLDCallback(bool class_unload) : _class_unload(class_unload) {}
do_cld(ClassLoaderData * cld)923 void do_cld(ClassLoaderData* cld) {
924 assert(cld != NULL, "invariant");
925 if (cld->is_unsafe_anonymous()) {
926 return;
927 }
928 if (_class_unload) {
929 JfrTypeSet::do_unloaded_class_loader_data(cld);
930 return;
931 }
932 JfrTypeSet::do_class_loader_data(cld);
933 }
934 };
935
do_class_loaders()936 void JfrTypeSet::do_class_loaders() {
937 CLDCallback cld_cb(_class_unload);
938 if (_class_unload) {
939 ClassLoaderDataGraph::cld_unloading_do(&cld_cb);
940 return;
941 }
942 ClassLoaderDataGraph::loaded_cld_do(&cld_cb);
943 }
944
clear_artifacts(JfrArtifactSet * artifacts,bool class_unload)945 static void clear_artifacts(JfrArtifactSet* artifacts,
946 bool class_unload) {
947 assert(artifacts != NULL, "invariant");
948 assert(artifacts->has_klass_entries(), "invariant");
949
950 // untag
951 ClearKlassAndMethods clear(class_unload);
952 artifacts->iterate_klasses(clear);
953 artifacts->clear();
954 }
955
956 /**
957 * Write all "tagged" (in-use) constant artifacts and their dependencies.
958 */
serialize(JfrCheckpointWriter * writer,JfrCheckpointWriter * leakp_writer,bool class_unload)959 void JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload) {
960 assert(writer != NULL, "invariant");
961 ResourceMark rm;
962 // initialization begin
963 _class_unload = class_unload;
964 ++checkpoint_id;
965 if (_artifacts == NULL) {
966 _artifacts = new JfrArtifactSet(class_unload);
967 _subsystem_callback = NULL;
968 } else {
969 _artifacts->initialize(class_unload);
970 _subsystem_callback = NULL;
971 }
972 assert(_artifacts != NULL, "invariant");
973 assert(!_artifacts->has_klass_entries(), "invariant");
974 assert(_subsystem_callback == NULL, "invariant");
975 // initialization complete
976
977 // write order is important because an individual write step
978 // might tag an artifact to be written in a subsequent step
979 write_klass_constants(writer, leakp_writer);
980 if (_artifacts->has_klass_entries()) {
981 write_package_constants(writer, leakp_writer);
982 write_module_constants(writer, leakp_writer);
983 write_class_loader_constants(writer, leakp_writer);
984 write_method_constants(writer, leakp_writer);
985 write_symbol_constants(writer, leakp_writer);
986 clear_artifacts(_artifacts, class_unload);
987 }
988 }
989