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