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 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 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 78 static traceid cld_id(CldPtr cld) { 79 assert(cld != NULL, "invariant"); 80 return cld->is_unsafe_anonymous() ? 0 : TRACE_ID(cld); 81 } 82 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: 103 TagLeakpKlassArtifact(bool class_unload) : _class_unload(class_unload) {} 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 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 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 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; 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 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; 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 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; 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 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 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 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 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 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 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; 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 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> 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> 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> 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> 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> 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: 498 ClearKlassAndMethods(bool class_unload) : _clear_klass_tag_bits(class_unload), 499 _clear_method_flag(class_unload), 500 _method_used_predicate(class_unload) {} 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 */ 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; 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 */ 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; 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 */ 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; 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 */ 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: 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 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 767 int count() const { return _method_functor.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 */ 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 } 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 } 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 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 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 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 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 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 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 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 } 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 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 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 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 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: 922 CLDCallback(bool class_unload) : _class_unload(class_unload) {} 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 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 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 */ 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 }