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, ®); 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, ®); 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 }