jvmtiTagMap.cpp revision 196:d1605aabd0a1
1/* 2 * Copyright 2003-2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25# include "incls/_precompiled.incl" 26# include "incls/_jvmtiTagMap.cpp.incl" 27 28// JvmtiTagHashmapEntry 29// 30// Each entry encapsulates a JNI weak reference to the tagged object 31// and the tag value. In addition an entry includes a next pointer which 32// is used to chain entries together. 33 34class JvmtiTagHashmapEntry : public CHeapObj { 35 private: 36 friend class JvmtiTagMap; 37 38 jweak _object; // JNI weak ref to tagged object 39 jlong _tag; // the tag 40 JvmtiTagHashmapEntry* _next; // next on the list 41 42 inline void init(jweak object, jlong tag) { 43 _object = object; 44 _tag = tag; 45 _next = NULL; 46 } 47 48 // constructor 49 JvmtiTagHashmapEntry(jweak object, jlong tag) { init(object, tag); } 50 51 public: 52 53 // accessor methods 54 inline jweak object() const { return _object; } 55 inline jlong tag() const { return _tag; } 56 57 inline void set_tag(jlong tag) { 58 assert(tag != 0, "can't be zero"); 59 _tag = tag; 60 } 61 62 inline JvmtiTagHashmapEntry* next() const { return _next; } 63 inline void set_next(JvmtiTagHashmapEntry* next) { _next = next; } 64}; 65 66 67// JvmtiTagHashmap 68// 69// A hashmap is essentially a table of pointers to entries. Entries 70// are hashed to a location, or position in the table, and then 71// chained from that location. The "key" for hashing is address of 72// the object, or oop. The "value" is the JNI weak reference to the 73// object and the tag value. Keys are not stored with the entry. 74// Instead the weak reference is resolved to obtain the key. 75// 76// A hashmap maintains a count of the number entries in the hashmap 77// and resizes if the number of entries exceeds a given threshold. 78// The threshold is specified as a percentage of the size - for 79// example a threshold of 0.75 will trigger the hashmap to resize 80// if the number of entries is >75% of table size. 81// 82// A hashmap provides functions for adding, removing, and finding 83// entries. It also provides a function to iterate over all entries 84// in the hashmap. 85 86class JvmtiTagHashmap : public CHeapObj { 87 private: 88 friend class JvmtiTagMap; 89 90 enum { 91 small_trace_threshold = 10000, // threshold for tracing 92 medium_trace_threshold = 100000, 93 large_trace_threshold = 1000000, 94 initial_trace_threshold = small_trace_threshold 95 }; 96 97 static int _sizes[]; // array of possible hashmap sizes 98 int _size; // actual size of the table 99 int _size_index; // index into size table 100 101 int _entry_count; // number of entries in the hashmap 102 103 float _load_factor; // load factor as a % of the size 104 int _resize_threshold; // computed threshold to trigger resizing. 105 bool _resizing_enabled; // indicates if hashmap can resize 106 107 int _trace_threshold; // threshold for trace messages 108 109 JvmtiTagHashmapEntry** _table; // the table of entries. 110 111 // private accessors 112 int resize_threshold() const { return _resize_threshold; } 113 int trace_threshold() const { return _trace_threshold; } 114 115 // initialize the hashmap 116 void init(int size_index=0, float load_factor=4.0f) { 117 int initial_size = _sizes[size_index]; 118 _size_index = size_index; 119 _size = initial_size; 120 _entry_count = 0; 121 if (TraceJVMTIObjectTagging) { 122 _trace_threshold = initial_trace_threshold; 123 } else { 124 _trace_threshold = -1; 125 } 126 _load_factor = load_factor; 127 _resize_threshold = (int)(_load_factor * _size); 128 _resizing_enabled = true; 129 size_t s = initial_size * sizeof(JvmtiTagHashmapEntry*); 130 _table = (JvmtiTagHashmapEntry**)os::malloc(s); 131 if (_table == NULL) { 132 vm_exit_out_of_memory(s, "unable to allocate initial hashtable for jvmti object tags"); 133 } 134 for (int i=0; i<initial_size; i++) { 135 _table[i] = NULL; 136 } 137 } 138 139 // hash a given key (oop) with the specified size 140 static unsigned int hash(oop key, int size) { 141 // shift right to get better distribution (as these bits will be zero 142 // with aligned addresses) 143 unsigned int addr = (unsigned int)((intptr_t)key); 144#ifdef _LP64 145 return (addr >> 3) % size; 146#else 147 return (addr >> 2) % size; 148#endif 149 } 150 151 // hash a given key (oop) 152 unsigned int hash(oop key) { 153 return hash(key, _size); 154 } 155 156 // resize the hashmap - allocates a large table and re-hashes 157 // all entries into the new table. 158 void resize() { 159 int new_size_index = _size_index+1; 160 int new_size = _sizes[new_size_index]; 161 if (new_size < 0) { 162 // hashmap already at maximum capacity 163 return; 164 } 165 166 // allocate new table 167 size_t s = new_size * sizeof(JvmtiTagHashmapEntry*); 168 JvmtiTagHashmapEntry** new_table = (JvmtiTagHashmapEntry**)os::malloc(s); 169 if (new_table == NULL) { 170 warning("unable to allocate larger hashtable for jvmti object tags"); 171 set_resizing_enabled(false); 172 return; 173 } 174 175 // initialize new table 176 int i; 177 for (i=0; i<new_size; i++) { 178 new_table[i] = NULL; 179 } 180 181 // rehash all entries into the new table 182 for (i=0; i<_size; i++) { 183 JvmtiTagHashmapEntry* entry = _table[i]; 184 while (entry != NULL) { 185 JvmtiTagHashmapEntry* next = entry->next(); 186 oop key = JNIHandles::resolve(entry->object()); 187 assert(key != NULL, "jni weak reference cleared!!"); 188 unsigned int h = hash(key, new_size); 189 JvmtiTagHashmapEntry* anchor = new_table[h]; 190 if (anchor == NULL) { 191 new_table[h] = entry; 192 entry->set_next(NULL); 193 } else { 194 entry->set_next(anchor); 195 new_table[h] = entry; 196 } 197 entry = next; 198 } 199 } 200 201 // free old table and update settings. 202 os::free((void*)_table); 203 _table = new_table; 204 _size_index = new_size_index; 205 _size = new_size; 206 207 // compute new resize threshold 208 _resize_threshold = (int)(_load_factor * _size); 209 } 210 211 212 // internal remove function - remove an entry at a given position in the 213 // table. 214 inline void remove(JvmtiTagHashmapEntry* prev, int pos, JvmtiTagHashmapEntry* entry) { 215 assert(pos >= 0 && pos < _size, "out of range"); 216 if (prev == NULL) { 217 _table[pos] = entry->next(); 218 } else { 219 prev->set_next(entry->next()); 220 } 221 assert(_entry_count > 0, "checking"); 222 _entry_count--; 223 } 224 225 // resizing switch 226 bool is_resizing_enabled() const { return _resizing_enabled; } 227 void set_resizing_enabled(bool enable) { _resizing_enabled = enable; } 228 229 // debugging 230 void print_memory_usage(); 231 void compute_next_trace_threshold(); 232 233 public: 234 235 // create a JvmtiTagHashmap of a preferred size and optionally a load factor. 236 // The preferred size is rounded down to an actual size. 237 JvmtiTagHashmap(int size, float load_factor=0.0f) { 238 int i=0; 239 while (_sizes[i] < size) { 240 if (_sizes[i] < 0) { 241 assert(i > 0, "sanity check"); 242 i--; 243 break; 244 } 245 i++; 246 } 247 248 // if a load factor is specified then use it, otherwise use default 249 if (load_factor > 0.01f) { 250 init(i, load_factor); 251 } else { 252 init(i); 253 } 254 } 255 256 // create a JvmtiTagHashmap with default settings 257 JvmtiTagHashmap() { 258 init(); 259 } 260 261 // release table when JvmtiTagHashmap destroyed 262 ~JvmtiTagHashmap() { 263 if (_table != NULL) { 264 os::free((void*)_table); 265 _table = NULL; 266 } 267 } 268 269 // accessors 270 int size() const { return _size; } 271 JvmtiTagHashmapEntry** table() const { return _table; } 272 int entry_count() const { return _entry_count; } 273 274 // find an entry in the hashmap, returns NULL if not found. 275 inline JvmtiTagHashmapEntry* find(oop key) { 276 unsigned int h = hash(key); 277 JvmtiTagHashmapEntry* entry = _table[h]; 278 while (entry != NULL) { 279 oop orig_key = JNIHandles::resolve(entry->object()); 280 assert(orig_key != NULL, "jni weak reference cleared!!"); 281 if (key == orig_key) { 282 break; 283 } 284 entry = entry->next(); 285 } 286 return entry; 287 } 288 289 290 // add a new entry to hashmap 291 inline void add(oop key, JvmtiTagHashmapEntry* entry) { 292 assert(key != NULL, "checking"); 293 assert(find(key) == NULL, "duplicate detected"); 294 unsigned int h = hash(key); 295 JvmtiTagHashmapEntry* anchor = _table[h]; 296 if (anchor == NULL) { 297 _table[h] = entry; 298 entry->set_next(NULL); 299 } else { 300 entry->set_next(anchor); 301 _table[h] = entry; 302 } 303 304 _entry_count++; 305 if (trace_threshold() > 0 && entry_count() >= trace_threshold()) { 306 assert(TraceJVMTIObjectTagging, "should only get here when tracing"); 307 print_memory_usage(); 308 compute_next_trace_threshold(); 309 } 310 311 // if the number of entries exceed the threshold then resize 312 if (entry_count() > resize_threshold() && is_resizing_enabled()) { 313 resize(); 314 } 315 } 316 317 // remove an entry with the given key. 318 inline JvmtiTagHashmapEntry* remove(oop key) { 319 unsigned int h = hash(key); 320 JvmtiTagHashmapEntry* entry = _table[h]; 321 JvmtiTagHashmapEntry* prev = NULL; 322 while (entry != NULL) { 323 oop orig_key = JNIHandles::resolve(entry->object()); 324 assert(orig_key != NULL, "jni weak reference cleared!!"); 325 if (key == orig_key) { 326 break; 327 } 328 prev = entry; 329 entry = entry->next(); 330 } 331 if (entry != NULL) { 332 remove(prev, h, entry); 333 } 334 return entry; 335 } 336 337 // iterate over all entries in the hashmap 338 void entry_iterate(JvmtiTagHashmapEntryClosure* closure); 339}; 340 341// possible hashmap sizes - odd primes that roughly double in size. 342// To avoid excessive resizing the odd primes from 4801-76831 and 343// 76831-307261 have been removed. The list must be terminated by -1. 344int JvmtiTagHashmap::_sizes[] = { 4801, 76831, 307261, 614563, 1228891, 345 2457733, 4915219, 9830479, 19660831, 39321619, 78643219, -1 }; 346 347 348// A supporting class for iterating over all entries in Hashmap 349class JvmtiTagHashmapEntryClosure { 350 public: 351 virtual void do_entry(JvmtiTagHashmapEntry* entry) = 0; 352}; 353 354 355// iterate over all entries in the hashmap 356void JvmtiTagHashmap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) { 357 for (int i=0; i<_size; i++) { 358 JvmtiTagHashmapEntry* entry = _table[i]; 359 JvmtiTagHashmapEntry* prev = NULL; 360 while (entry != NULL) { 361 // obtain the next entry before invoking do_entry - this is 362 // necessary because do_entry may remove the entry from the 363 // hashmap. 364 JvmtiTagHashmapEntry* next = entry->next(); 365 closure->do_entry(entry); 366 entry = next; 367 } 368 } 369} 370 371// debugging 372void JvmtiTagHashmap::print_memory_usage() { 373 intptr_t p = (intptr_t)this; 374 tty->print("[JvmtiTagHashmap @ " INTPTR_FORMAT, p); 375 376 // table + entries in KB 377 int hashmap_usage = (size()*sizeof(JvmtiTagHashmapEntry*) + 378 entry_count()*sizeof(JvmtiTagHashmapEntry))/K; 379 380 int weak_globals_usage = (int)(JNIHandles::weak_global_handle_memory_usage()/K); 381 tty->print_cr(", %d entries (%d KB) <JNI weak globals: %d KB>]", 382 entry_count(), hashmap_usage, weak_globals_usage); 383} 384 385// compute threshold for the next trace message 386void JvmtiTagHashmap::compute_next_trace_threshold() { 387 if (trace_threshold() < medium_trace_threshold) { 388 _trace_threshold += small_trace_threshold; 389 } else { 390 if (trace_threshold() < large_trace_threshold) { 391 _trace_threshold += medium_trace_threshold; 392 } else { 393 _trace_threshold += large_trace_threshold; 394 } 395 } 396} 397 398// memory region for young generation 399MemRegion JvmtiTagMap::_young_gen; 400 401// get the memory region used for the young generation 402void JvmtiTagMap::get_young_generation() { 403 if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) { 404 GenCollectedHeap* gch = GenCollectedHeap::heap(); 405 _young_gen = gch->get_gen(0)->reserved(); 406 } else { 407#ifndef SERIALGC 408 ParallelScavengeHeap* psh = ParallelScavengeHeap::heap(); 409 _young_gen= psh->young_gen()->reserved(); 410#else // SERIALGC 411 fatal("SerialGC only supported in this configuration."); 412#endif // SERIALGC 413 } 414} 415 416// returns true if oop is in the young generation 417inline bool JvmtiTagMap::is_in_young(oop o) { 418 assert(_young_gen.start() != NULL, "checking"); 419 void* p = (void*)o; 420 bool in_young = _young_gen.contains(p); 421 return in_young; 422} 423 424// returns the appropriate hashmap for a given object 425inline JvmtiTagHashmap* JvmtiTagMap::hashmap_for(oop o) { 426 if (is_in_young(o)) { 427 return _hashmap[0]; 428 } else { 429 return _hashmap[1]; 430 } 431} 432 433 434// create a JvmtiTagMap 435JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) : 436 _env(env), 437 _lock(Mutex::nonleaf+2, "JvmtiTagMap._lock", false), 438 _free_entries(NULL), 439 _free_entries_count(0) 440{ 441 assert(JvmtiThreadState_lock->is_locked(), "sanity check"); 442 assert(((JvmtiEnvBase *)env)->tag_map() == NULL, "tag map already exists for environment"); 443 444 // create the hashmaps 445 for (int i=0; i<n_hashmaps; i++) { 446 _hashmap[i] = new JvmtiTagHashmap(); 447 } 448 449 // get the memory region used by the young generation 450 get_young_generation(); 451 452 // finally add us to the environment 453 ((JvmtiEnvBase *)env)->set_tag_map(this); 454} 455 456 457// destroy a JvmtiTagMap 458JvmtiTagMap::~JvmtiTagMap() { 459 460 // no lock acquired as we assume the enclosing environment is 461 // also being destroryed. 462 ((JvmtiEnvBase *)_env)->set_tag_map(NULL); 463 464 // iterate over the hashmaps and destroy each of the entries 465 for (int i=0; i<n_hashmaps; i++) { 466 JvmtiTagHashmap* hashmap = _hashmap[i]; 467 JvmtiTagHashmapEntry** table = hashmap->table(); 468 for (int j=0; j<hashmap->size(); j++) { 469 JvmtiTagHashmapEntry *entry = table[j]; 470 while (entry != NULL) { 471 JvmtiTagHashmapEntry* next = entry->next(); 472 jweak ref = entry->object(); 473 JNIHandles::destroy_weak_global(ref); 474 delete entry; 475 entry = next; 476 } 477 } 478 479 // finally destroy the hashmap 480 delete hashmap; 481 } 482 483 // remove any entries on the free list 484 JvmtiTagHashmapEntry* entry = _free_entries; 485 while (entry != NULL) { 486 JvmtiTagHashmapEntry* next = entry->next(); 487 delete entry; 488 entry = next; 489 } 490} 491 492// create a hashmap entry 493// - if there's an entry on the (per-environment) free list then this 494// is returned. Otherwise an new entry is allocated. 495JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(jweak ref, jlong tag) { 496 assert(Thread::current()->is_VM_thread() || is_locked(), "checking"); 497 JvmtiTagHashmapEntry* entry; 498 if (_free_entries == NULL) { 499 entry = new JvmtiTagHashmapEntry(ref, tag); 500 } else { 501 assert(_free_entries_count > 0, "mismatched _free_entries_count"); 502 _free_entries_count--; 503 entry = _free_entries; 504 _free_entries = entry->next(); 505 entry->init(ref, tag); 506 } 507 return entry; 508} 509 510// destroy an entry by returning it to the free list 511void JvmtiTagMap::destroy_entry(JvmtiTagHashmapEntry* entry) { 512 assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking"); 513 // limit the size of the free list 514 if (_free_entries_count >= max_free_entries) { 515 delete entry; 516 } else { 517 entry->set_next(_free_entries); 518 _free_entries = entry; 519 _free_entries_count++; 520 } 521} 522 523// returns the tag map for the given environments. If the tag map 524// doesn't exist then it is created. 525JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) { 526 JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map(); 527 if (tag_map == NULL) { 528 MutexLocker mu(JvmtiThreadState_lock); 529 tag_map = ((JvmtiEnvBase *)env)->tag_map(); 530 if (tag_map == NULL) { 531 tag_map = new JvmtiTagMap(env); 532 } 533 } else { 534 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); 535 } 536 return tag_map; 537} 538 539// iterate over all entries in the tag map. 540void JvmtiTagMap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) { 541 for (int i=0; i<n_hashmaps; i++) { 542 JvmtiTagHashmap* hashmap = _hashmap[i]; 543 hashmap->entry_iterate(closure); 544 } 545} 546 547// returns true if the hashmaps are empty 548bool JvmtiTagMap::is_empty() { 549 assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking"); 550 assert(n_hashmaps == 2, "not implemented"); 551 return ((_hashmap[0]->entry_count() == 0) && (_hashmap[1]->entry_count() == 0)); 552} 553 554 555// Return the tag value for an object, or 0 if the object is 556// not tagged 557// 558static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) { 559 JvmtiTagHashmapEntry* entry = tag_map->hashmap_for(o)->find(o); 560 if (entry == NULL) { 561 return 0; 562 } else { 563 return entry->tag(); 564 } 565} 566 567// If the object is a java.lang.Class then return the klassOop, 568// otherwise return the original object 569static inline oop klassOop_if_java_lang_Class(oop o) { 570 if (o->klass() == SystemDictionary::class_klass()) { 571 if (!java_lang_Class::is_primitive(o)) { 572 o = (oop)java_lang_Class::as_klassOop(o); 573 assert(o != NULL, "class for non-primitive mirror must exist"); 574 } 575 } 576 return o; 577} 578 579// A CallbackWrapper is a support class for querying and tagging an object 580// around a callback to a profiler. The constructor does pre-callback 581// work to get the tag value, klass tag value, ... and the destructor 582// does the post-callback work of tagging or untagging the object. 583// 584// { 585// CallbackWrapper wrapper(tag_map, o); 586// 587// (*callback)(wrapper.klass_tag(), wrapper.obj_size(), wrapper.obj_tag_p(), ...) 588// 589// } // wrapper goes out of scope here which results in the destructor 590// checking to see if the object has been tagged, untagged, or the 591// tag value has changed. 592// 593class CallbackWrapper : public StackObj { 594 private: 595 JvmtiTagMap* _tag_map; 596 JvmtiTagHashmap* _hashmap; 597 JvmtiTagHashmapEntry* _entry; 598 oop _o; 599 jlong _obj_size; 600 jlong _obj_tag; 601 klassOop _klass; // the object's class 602 jlong _klass_tag; 603 604 protected: 605 JvmtiTagMap* tag_map() const { return _tag_map; } 606 607 // invoked post-callback to tag, untag, or update the tag of an object 608 void inline post_callback_tag_update(oop o, JvmtiTagHashmap* hashmap, 609 JvmtiTagHashmapEntry* entry, jlong obj_tag); 610 public: 611 CallbackWrapper(JvmtiTagMap* tag_map, oop o) { 612 assert(Thread::current()->is_VM_thread() || tag_map->is_locked(), 613 "MT unsafe or must be VM thread"); 614 615 // for Classes the klassOop is tagged 616 _o = klassOop_if_java_lang_Class(o); 617 618 // object size 619 _obj_size = _o->size() * wordSize; 620 621 // record the context 622 _tag_map = tag_map; 623 _hashmap = tag_map->hashmap_for(_o); 624 _entry = _hashmap->find(_o); 625 626 // get object tag 627 _obj_tag = (_entry == NULL) ? 0 : _entry->tag(); 628 629 // get the class and the class's tag value 630 if (_o == o) { 631 _klass = _o->klass(); 632 } else { 633 // if the object represents a runtime class then use the 634 // tag for java.lang.Class 635 _klass = SystemDictionary::class_klass(); 636 } 637 _klass_tag = tag_for(tag_map, _klass); 638 } 639 640 ~CallbackWrapper() { 641 post_callback_tag_update(_o, _hashmap, _entry, _obj_tag); 642 } 643 644 inline jlong* obj_tag_p() { return &_obj_tag; } 645 inline jlong obj_size() const { return _obj_size; } 646 inline jlong obj_tag() const { return _obj_tag; } 647 inline klassOop klass() const { return _klass; } 648 inline jlong klass_tag() const { return _klass_tag; } 649}; 650 651 652 653// callback post-callback to tag, untag, or update the tag of an object 654void inline CallbackWrapper::post_callback_tag_update(oop o, 655 JvmtiTagHashmap* hashmap, 656 JvmtiTagHashmapEntry* entry, 657 jlong obj_tag) { 658 if (entry == NULL) { 659 if (obj_tag != 0) { 660 // callback has tagged the object 661 assert(Thread::current()->is_VM_thread(), "must be VMThread"); 662 HandleMark hm; 663 Handle h(o); 664 jweak ref = JNIHandles::make_weak_global(h); 665 entry = tag_map()->create_entry(ref, obj_tag); 666 hashmap->add(o, entry); 667 } 668 } else { 669 // object was previously tagged - the callback may have untagged 670 // the object or changed the tag value 671 if (obj_tag == 0) { 672 jweak ref = entry->object(); 673 674 JvmtiTagHashmapEntry* entry_removed = hashmap->remove(o); 675 assert(entry_removed == entry, "checking"); 676 tag_map()->destroy_entry(entry); 677 678 JNIHandles::destroy_weak_global(ref); 679 } else { 680 if (obj_tag != entry->tag()) { 681 entry->set_tag(obj_tag); 682 } 683 } 684 } 685} 686 687// An extended CallbackWrapper used when reporting an object reference 688// to the agent. 689// 690// { 691// TwoOopCallbackWrapper wrapper(tag_map, referrer, o); 692// 693// (*callback)(wrapper.klass_tag(), 694// wrapper.obj_size(), 695// wrapper.obj_tag_p() 696// wrapper.referrer_tag_p(), ...) 697// 698// } // wrapper goes out of scope here which results in the destructor 699// checking to see if the referrer object has been tagged, untagged, 700// or the tag value has changed. 701// 702class TwoOopCallbackWrapper : public CallbackWrapper { 703 private: 704 bool _is_reference_to_self; 705 JvmtiTagHashmap* _referrer_hashmap; 706 JvmtiTagHashmapEntry* _referrer_entry; 707 oop _referrer; 708 jlong _referrer_obj_tag; 709 jlong _referrer_klass_tag; 710 jlong* _referrer_tag_p; 711 712 bool is_reference_to_self() const { return _is_reference_to_self; } 713 714 public: 715 TwoOopCallbackWrapper(JvmtiTagMap* tag_map, oop referrer, oop o) : 716 CallbackWrapper(tag_map, o) 717 { 718 // self reference needs to be handled in a special way 719 _is_reference_to_self = (referrer == o); 720 721 if (_is_reference_to_self) { 722 _referrer_klass_tag = klass_tag(); 723 _referrer_tag_p = obj_tag_p(); 724 } else { 725 // for Classes the klassOop is tagged 726 _referrer = klassOop_if_java_lang_Class(referrer); 727 // record the context 728 _referrer_hashmap = tag_map->hashmap_for(_referrer); 729 _referrer_entry = _referrer_hashmap->find(_referrer); 730 731 // get object tag 732 _referrer_obj_tag = (_referrer_entry == NULL) ? 0 : _referrer_entry->tag(); 733 _referrer_tag_p = &_referrer_obj_tag; 734 735 // get referrer class tag. 736 klassOop k = (_referrer == referrer) ? // Check if referrer is a class... 737 _referrer->klass() // No, just get its class 738 : SystemDictionary::class_klass(); // Yes, its class is Class 739 _referrer_klass_tag = tag_for(tag_map, k); 740 } 741 } 742 743 ~TwoOopCallbackWrapper() { 744 if (!is_reference_to_self()){ 745 post_callback_tag_update(_referrer, 746 _referrer_hashmap, 747 _referrer_entry, 748 _referrer_obj_tag); 749 } 750 } 751 752 // address of referrer tag 753 // (for a self reference this will return the same thing as obj_tag_p()) 754 inline jlong* referrer_tag_p() { return _referrer_tag_p; } 755 756 // referrer's class tag 757 inline jlong referrer_klass_tag() { return _referrer_klass_tag; } 758}; 759 760// tag an object 761// 762// This function is performance critical. If many threads attempt to tag objects 763// around the same time then it's possible that the Mutex associated with the 764// tag map will be a hot lock. Eliminating this lock will not eliminate the issue 765// because creating a JNI weak reference requires acquiring a global lock also. 766void JvmtiTagMap::set_tag(jobject object, jlong tag) { 767 MutexLocker ml(lock()); 768 769 // resolve the object 770 oop o = JNIHandles::resolve_non_null(object); 771 772 // for Classes we tag the klassOop 773 o = klassOop_if_java_lang_Class(o); 774 775 // see if the object is already tagged 776 JvmtiTagHashmap* hashmap = hashmap_for(o); 777 JvmtiTagHashmapEntry* entry = hashmap->find(o); 778 779 // if the object is not already tagged then we tag it 780 if (entry == NULL) { 781 if (tag != 0) { 782 HandleMark hm; 783 Handle h(o); 784 jweak ref = JNIHandles::make_weak_global(h); 785 786 // the object may have moved because make_weak_global may 787 // have blocked - thus it is necessary resolve the handle 788 // and re-hash the object. 789 o = h(); 790 entry = create_entry(ref, tag); 791 hashmap_for(o)->add(o, entry); 792 } else { 793 // no-op 794 } 795 } else { 796 // if the object is already tagged then we either update 797 // the tag (if a new tag value has been provided) 798 // or remove the object if the new tag value is 0. 799 // Removing the object requires that we also delete the JNI 800 // weak ref to the object. 801 if (tag == 0) { 802 jweak ref = entry->object(); 803 hashmap->remove(o); 804 destroy_entry(entry); 805 JNIHandles::destroy_weak_global(ref); 806 } else { 807 entry->set_tag(tag); 808 } 809 } 810} 811 812// get the tag for an object 813jlong JvmtiTagMap::get_tag(jobject object) { 814 MutexLocker ml(lock()); 815 816 // resolve the object 817 oop o = JNIHandles::resolve_non_null(object); 818 819 // for Classes get the tag from the klassOop 820 return tag_for(this, klassOop_if_java_lang_Class(o)); 821} 822 823 824// Helper class used to describe the static or instance fields of a class. 825// For each field it holds the field index (as defined by the JVMTI specification), 826// the field type, and the offset. 827 828class ClassFieldDescriptor: public CHeapObj { 829 private: 830 int _field_index; 831 int _field_offset; 832 char _field_type; 833 public: 834 ClassFieldDescriptor(int index, char type, int offset) : 835 _field_index(index), _field_type(type), _field_offset(offset) { 836 } 837 int field_index() const { return _field_index; } 838 char field_type() const { return _field_type; } 839 int field_offset() const { return _field_offset; } 840}; 841 842class ClassFieldMap: public CHeapObj { 843 private: 844 enum { 845 initial_field_count = 5 846 }; 847 848 // list of field descriptors 849 GrowableArray<ClassFieldDescriptor*>* _fields; 850 851 // constructor 852 ClassFieldMap(); 853 854 // add a field 855 void add(int index, char type, int offset); 856 857 // returns the field count for the given class 858 static int compute_field_count(instanceKlassHandle ikh); 859 860 public: 861 ~ClassFieldMap(); 862 863 // access 864 int field_count() { return _fields->length(); } 865 ClassFieldDescriptor* field_at(int i) { return _fields->at(i); } 866 867 // functions to create maps of static or instance fields 868 static ClassFieldMap* create_map_of_static_fields(klassOop k); 869 static ClassFieldMap* create_map_of_instance_fields(oop obj); 870}; 871 872ClassFieldMap::ClassFieldMap() { 873 _fields = new (ResourceObj::C_HEAP) GrowableArray<ClassFieldDescriptor*>(initial_field_count, true); 874} 875 876ClassFieldMap::~ClassFieldMap() { 877 for (int i=0; i<_fields->length(); i++) { 878 delete _fields->at(i); 879 } 880 delete _fields; 881} 882 883void ClassFieldMap::add(int index, char type, int offset) { 884 ClassFieldDescriptor* field = new ClassFieldDescriptor(index, type, offset); 885 _fields->append(field); 886} 887 888// Returns a heap allocated ClassFieldMap to describe the static fields 889// of the given class. 890// 891ClassFieldMap* ClassFieldMap::create_map_of_static_fields(klassOop k) { 892 HandleMark hm; 893 instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); 894 895 // create the field map 896 ClassFieldMap* field_map = new ClassFieldMap(); 897 898 FilteredFieldStream f(ikh, false, false); 899 int max_field_index = f.field_count()-1; 900 901 int index = 0; 902 for (FilteredFieldStream fld(ikh, true, true); !fld.eos(); fld.next(), index++) { 903 // ignore instance fields 904 if (!fld.access_flags().is_static()) { 905 continue; 906 } 907 field_map->add(max_field_index - index, fld.signature()->byte_at(0), fld.offset()); 908 } 909 return field_map; 910} 911 912// Returns a heap allocated ClassFieldMap to describe the instance fields 913// of the given class. All instance fields are included (this means public 914// and private fields declared in superclasses and superinterfaces too). 915// 916ClassFieldMap* ClassFieldMap::create_map_of_instance_fields(oop obj) { 917 HandleMark hm; 918 instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), obj->klass()); 919 920 // create the field map 921 ClassFieldMap* field_map = new ClassFieldMap(); 922 923 FilteredFieldStream f(ikh, false, false); 924 925 int max_field_index = f.field_count()-1; 926 927 int index = 0; 928 for (FilteredFieldStream fld(ikh, false, false); !fld.eos(); fld.next(), index++) { 929 // ignore static fields 930 if (fld.access_flags().is_static()) { 931 continue; 932 } 933 field_map->add(max_field_index - index, fld.signature()->byte_at(0), fld.offset()); 934 } 935 936 return field_map; 937} 938 939// Helper class used to cache a ClassFileMap for the instance fields of 940// a cache. A JvmtiCachedClassFieldMap can be cached by an instanceKlass during 941// heap iteration and avoid creating a field map for each object in the heap 942// (only need to create the map when the first instance of a class is encountered). 943// 944class JvmtiCachedClassFieldMap : public CHeapObj { 945 private: 946 enum { 947 initial_class_count = 200 948 }; 949 ClassFieldMap* _field_map; 950 951 ClassFieldMap* field_map() const { return _field_map; } 952 953 JvmtiCachedClassFieldMap(ClassFieldMap* field_map); 954 ~JvmtiCachedClassFieldMap(); 955 956 static GrowableArray<instanceKlass*>* _class_list; 957 static void add_to_class_list(instanceKlass* ik); 958 959 public: 960 // returns the field map for a given object (returning map cached 961 // by instanceKlass if possible 962 static ClassFieldMap* get_map_of_instance_fields(oop obj); 963 964 // removes the field map from all instanceKlasses - should be 965 // called before VM operation completes 966 static void clear_cache(); 967 968 // returns the number of ClassFieldMap cached by instanceKlasses 969 static int cached_field_map_count(); 970}; 971 972GrowableArray<instanceKlass*>* JvmtiCachedClassFieldMap::_class_list; 973 974JvmtiCachedClassFieldMap::JvmtiCachedClassFieldMap(ClassFieldMap* field_map) { 975 _field_map = field_map; 976} 977 978JvmtiCachedClassFieldMap::~JvmtiCachedClassFieldMap() { 979 if (_field_map != NULL) { 980 delete _field_map; 981 } 982} 983 984// Marker class to ensure that the class file map cache is only used in a defined 985// scope. 986class ClassFieldMapCacheMark : public StackObj { 987 private: 988 static bool _is_active; 989 public: 990 ClassFieldMapCacheMark() { 991 assert(Thread::current()->is_VM_thread(), "must be VMThread"); 992 assert(JvmtiCachedClassFieldMap::cached_field_map_count() == 0, "cache not empty"); 993 assert(!_is_active, "ClassFieldMapCacheMark cannot be nested"); 994 _is_active = true; 995 } 996 ~ClassFieldMapCacheMark() { 997 JvmtiCachedClassFieldMap::clear_cache(); 998 _is_active = false; 999 } 1000 static bool is_active() { return _is_active; } 1001}; 1002 1003bool ClassFieldMapCacheMark::_is_active; 1004 1005 1006// record that the given instanceKlass is caching a field map 1007void JvmtiCachedClassFieldMap::add_to_class_list(instanceKlass* ik) { 1008 if (_class_list == NULL) { 1009 _class_list = new (ResourceObj::C_HEAP) GrowableArray<instanceKlass*>(initial_class_count, true); 1010 } 1011 _class_list->push(ik); 1012} 1013 1014// returns the instance field map for the given object 1015// (returns field map cached by the instanceKlass if possible) 1016ClassFieldMap* JvmtiCachedClassFieldMap::get_map_of_instance_fields(oop obj) { 1017 assert(Thread::current()->is_VM_thread(), "must be VMThread"); 1018 assert(ClassFieldMapCacheMark::is_active(), "ClassFieldMapCacheMark not active"); 1019 1020 klassOop k = obj->klass(); 1021 instanceKlass* ik = instanceKlass::cast(k); 1022 1023 // return cached map if possible 1024 JvmtiCachedClassFieldMap* cached_map = ik->jvmti_cached_class_field_map(); 1025 if (cached_map != NULL) { 1026 assert(cached_map->field_map() != NULL, "missing field list"); 1027 return cached_map->field_map(); 1028 } else { 1029 ClassFieldMap* field_map = ClassFieldMap::create_map_of_instance_fields(obj); 1030 cached_map = new JvmtiCachedClassFieldMap(field_map); 1031 ik->set_jvmti_cached_class_field_map(cached_map); 1032 add_to_class_list(ik); 1033 return field_map; 1034 } 1035} 1036 1037// remove the fields maps cached from all instanceKlasses 1038void JvmtiCachedClassFieldMap::clear_cache() { 1039 assert(Thread::current()->is_VM_thread(), "must be VMThread"); 1040 if (_class_list != NULL) { 1041 for (int i = 0; i < _class_list->length(); i++) { 1042 instanceKlass* ik = _class_list->at(i); 1043 JvmtiCachedClassFieldMap* cached_map = ik->jvmti_cached_class_field_map(); 1044 assert(cached_map != NULL, "should not be NULL"); 1045 ik->set_jvmti_cached_class_field_map(NULL); 1046 delete cached_map; // deletes the encapsulated field map 1047 } 1048 delete _class_list; 1049 _class_list = NULL; 1050 } 1051} 1052 1053// returns the number of ClassFieldMap cached by instanceKlasses 1054int JvmtiCachedClassFieldMap::cached_field_map_count() { 1055 return (_class_list == NULL) ? 0 : _class_list->length(); 1056} 1057 1058// helper function to indicate if an object is filtered by its tag or class tag 1059static inline bool is_filtered_by_heap_filter(jlong obj_tag, 1060 jlong klass_tag, 1061 int heap_filter) { 1062 // apply the heap filter 1063 if (obj_tag != 0) { 1064 // filter out tagged objects 1065 if (heap_filter & JVMTI_HEAP_FILTER_TAGGED) return true; 1066 } else { 1067 // filter out untagged objects 1068 if (heap_filter & JVMTI_HEAP_FILTER_UNTAGGED) return true; 1069 } 1070 if (klass_tag != 0) { 1071 // filter out objects with tagged classes 1072 if (heap_filter & JVMTI_HEAP_FILTER_CLASS_TAGGED) return true; 1073 } else { 1074 // filter out objects with untagged classes. 1075 if (heap_filter & JVMTI_HEAP_FILTER_CLASS_UNTAGGED) return true; 1076 } 1077 return false; 1078} 1079 1080// helper function to indicate if an object is filtered by a klass filter 1081static inline bool is_filtered_by_klass_filter(oop obj, KlassHandle klass_filter) { 1082 if (!klass_filter.is_null()) { 1083 if (obj->klass() != klass_filter()) { 1084 return true; 1085 } 1086 } 1087 return false; 1088} 1089 1090// helper function to tell if a field is a primitive field or not 1091static inline bool is_primitive_field_type(char type) { 1092 return (type != 'L' && type != '['); 1093} 1094 1095// helper function to copy the value from location addr to jvalue. 1096static inline void copy_to_jvalue(jvalue *v, address addr, jvmtiPrimitiveType value_type) { 1097 switch (value_type) { 1098 case JVMTI_PRIMITIVE_TYPE_BOOLEAN : { v->z = *(jboolean*)addr; break; } 1099 case JVMTI_PRIMITIVE_TYPE_BYTE : { v->b = *(jbyte*)addr; break; } 1100 case JVMTI_PRIMITIVE_TYPE_CHAR : { v->c = *(jchar*)addr; break; } 1101 case JVMTI_PRIMITIVE_TYPE_SHORT : { v->s = *(jshort*)addr; break; } 1102 case JVMTI_PRIMITIVE_TYPE_INT : { v->i = *(jint*)addr; break; } 1103 case JVMTI_PRIMITIVE_TYPE_LONG : { v->j = *(jlong*)addr; break; } 1104 case JVMTI_PRIMITIVE_TYPE_FLOAT : { v->f = *(jfloat*)addr; break; } 1105 case JVMTI_PRIMITIVE_TYPE_DOUBLE : { v->d = *(jdouble*)addr; break; } 1106 default: ShouldNotReachHere(); 1107 } 1108} 1109 1110// helper function to invoke string primitive value callback 1111// returns visit control flags 1112static jint invoke_string_value_callback(jvmtiStringPrimitiveValueCallback cb, 1113 CallbackWrapper* wrapper, 1114 oop str, 1115 void* user_data) 1116{ 1117 assert(str->klass() == SystemDictionary::string_klass(), "not a string"); 1118 1119 // get the string value and length 1120 // (string value may be offset from the base) 1121 int s_len = java_lang_String::length(str); 1122 typeArrayOop s_value = java_lang_String::value(str); 1123 int s_offset = java_lang_String::offset(str); 1124 jchar* value; 1125 if (s_len > 0) { 1126 value = s_value->char_at_addr(s_offset); 1127 } else { 1128 value = (jchar*) s_value->base(T_CHAR); 1129 } 1130 1131 // invoke the callback 1132 return (*cb)(wrapper->klass_tag(), 1133 wrapper->obj_size(), 1134 wrapper->obj_tag_p(), 1135 value, 1136 (jint)s_len, 1137 user_data); 1138} 1139 1140// helper function to invoke string primitive value callback 1141// returns visit control flags 1142static jint invoke_array_primitive_value_callback(jvmtiArrayPrimitiveValueCallback cb, 1143 CallbackWrapper* wrapper, 1144 oop obj, 1145 void* user_data) 1146{ 1147 assert(obj->is_typeArray(), "not a primitive array"); 1148 1149 // get base address of first element 1150 typeArrayOop array = typeArrayOop(obj); 1151 BasicType type = typeArrayKlass::cast(array->klass())->element_type(); 1152 void* elements = array->base(type); 1153 1154 // jvmtiPrimitiveType is defined so this mapping is always correct 1155 jvmtiPrimitiveType elem_type = (jvmtiPrimitiveType)type2char(type); 1156 1157 return (*cb)(wrapper->klass_tag(), 1158 wrapper->obj_size(), 1159 wrapper->obj_tag_p(), 1160 (jint)array->length(), 1161 elem_type, 1162 elements, 1163 user_data); 1164} 1165 1166// helper function to invoke the primitive field callback for all static fields 1167// of a given class 1168static jint invoke_primitive_field_callback_for_static_fields 1169 (CallbackWrapper* wrapper, 1170 oop obj, 1171 jvmtiPrimitiveFieldCallback cb, 1172 void* user_data) 1173{ 1174 // for static fields only the index will be set 1175 static jvmtiHeapReferenceInfo reference_info = { 0 }; 1176 1177 assert(obj->klass() == SystemDictionary::class_klass(), "not a class"); 1178 if (java_lang_Class::is_primitive(obj)) { 1179 return 0; 1180 } 1181 klassOop k = java_lang_Class::as_klassOop(obj); 1182 Klass* klass = k->klass_part(); 1183 1184 // ignore classes for object and type arrays 1185 if (!klass->oop_is_instance()) { 1186 return 0; 1187 } 1188 1189 // ignore classes which aren't linked yet 1190 instanceKlass* ik = instanceKlass::cast(k); 1191 if (!ik->is_linked()) { 1192 return 0; 1193 } 1194 1195 // get the field map 1196 ClassFieldMap* field_map = ClassFieldMap::create_map_of_static_fields(k); 1197 1198 // invoke the callback for each static primitive field 1199 for (int i=0; i<field_map->field_count(); i++) { 1200 ClassFieldDescriptor* field = field_map->field_at(i); 1201 1202 // ignore non-primitive fields 1203 char type = field->field_type(); 1204 if (!is_primitive_field_type(type)) { 1205 continue; 1206 } 1207 // one-to-one mapping 1208 jvmtiPrimitiveType value_type = (jvmtiPrimitiveType)type; 1209 1210 // get offset and field value 1211 int offset = field->field_offset(); 1212 address addr = (address)k + offset; 1213 jvalue value; 1214 copy_to_jvalue(&value, addr, value_type); 1215 1216 // field index 1217 reference_info.field.index = field->field_index(); 1218 1219 // invoke the callback 1220 jint res = (*cb)(JVMTI_HEAP_REFERENCE_STATIC_FIELD, 1221 &reference_info, 1222 wrapper->klass_tag(), 1223 wrapper->obj_tag_p(), 1224 value, 1225 value_type, 1226 user_data); 1227 if (res & JVMTI_VISIT_ABORT) { 1228 delete field_map; 1229 return res; 1230 } 1231 } 1232 1233 delete field_map; 1234 return 0; 1235} 1236 1237// helper function to invoke the primitive field callback for all instance fields 1238// of a given object 1239static jint invoke_primitive_field_callback_for_instance_fields( 1240 CallbackWrapper* wrapper, 1241 oop obj, 1242 jvmtiPrimitiveFieldCallback cb, 1243 void* user_data) 1244{ 1245 // for instance fields only the index will be set 1246 static jvmtiHeapReferenceInfo reference_info = { 0 }; 1247 1248 // get the map of the instance fields 1249 ClassFieldMap* fields = JvmtiCachedClassFieldMap::get_map_of_instance_fields(obj); 1250 1251 // invoke the callback for each instance primitive field 1252 for (int i=0; i<fields->field_count(); i++) { 1253 ClassFieldDescriptor* field = fields->field_at(i); 1254 1255 // ignore non-primitive fields 1256 char type = field->field_type(); 1257 if (!is_primitive_field_type(type)) { 1258 continue; 1259 } 1260 // one-to-one mapping 1261 jvmtiPrimitiveType value_type = (jvmtiPrimitiveType)type; 1262 1263 // get offset and field value 1264 int offset = field->field_offset(); 1265 address addr = (address)obj + offset; 1266 jvalue value; 1267 copy_to_jvalue(&value, addr, value_type); 1268 1269 // field index 1270 reference_info.field.index = field->field_index(); 1271 1272 // invoke the callback 1273 jint res = (*cb)(JVMTI_HEAP_REFERENCE_FIELD, 1274 &reference_info, 1275 wrapper->klass_tag(), 1276 wrapper->obj_tag_p(), 1277 value, 1278 value_type, 1279 user_data); 1280 if (res & JVMTI_VISIT_ABORT) { 1281 return res; 1282 } 1283 } 1284 return 0; 1285} 1286 1287 1288// VM operation to iterate over all objects in the heap (both reachable 1289// and unreachable) 1290class VM_HeapIterateOperation: public VM_Operation { 1291 private: 1292 ObjectClosure* _blk; 1293 public: 1294 VM_HeapIterateOperation(ObjectClosure* blk) { _blk = blk; } 1295 1296 VMOp_Type type() const { return VMOp_HeapIterateOperation; } 1297 void doit() { 1298 // allows class files maps to be cached during iteration 1299 ClassFieldMapCacheMark cm; 1300 1301 // make sure that heap is parsable (fills TLABs with filler objects) 1302 Universe::heap()->ensure_parsability(false); // no need to retire TLABs 1303 1304 // Verify heap before iteration - if the heap gets corrupted then 1305 // JVMTI's IterateOverHeap will crash. 1306 if (VerifyBeforeIteration) { 1307 Universe::verify(); 1308 } 1309 1310 // do the iteration 1311 Universe::heap()->object_iterate(_blk); 1312 1313 // when sharing is enabled we must iterate over the shared spaces 1314 if (UseSharedSpaces) { 1315 GenCollectedHeap* gch = GenCollectedHeap::heap(); 1316 CompactingPermGenGen* gen = (CompactingPermGenGen*)gch->perm_gen(); 1317 gen->ro_space()->object_iterate(_blk); 1318 gen->rw_space()->object_iterate(_blk); 1319 } 1320 } 1321 1322}; 1323 1324 1325// An ObjectClosure used to support the deprecated IterateOverHeap and 1326// IterateOverInstancesOfClass functions 1327class IterateOverHeapObjectClosure: public ObjectClosure { 1328 private: 1329 JvmtiTagMap* _tag_map; 1330 KlassHandle _klass; 1331 jvmtiHeapObjectFilter _object_filter; 1332 jvmtiHeapObjectCallback _heap_object_callback; 1333 const void* _user_data; 1334 1335 // accessors 1336 JvmtiTagMap* tag_map() const { return _tag_map; } 1337 jvmtiHeapObjectFilter object_filter() const { return _object_filter; } 1338 jvmtiHeapObjectCallback object_callback() const { return _heap_object_callback; } 1339 KlassHandle klass() const { return _klass; } 1340 const void* user_data() const { return _user_data; } 1341 1342 // indicates if iteration has been aborted 1343 bool _iteration_aborted; 1344 bool is_iteration_aborted() const { return _iteration_aborted; } 1345 void set_iteration_aborted(bool aborted) { _iteration_aborted = aborted; } 1346 1347 public: 1348 IterateOverHeapObjectClosure(JvmtiTagMap* tag_map, 1349 KlassHandle klass, 1350 jvmtiHeapObjectFilter object_filter, 1351 jvmtiHeapObjectCallback heap_object_callback, 1352 const void* user_data) : 1353 _tag_map(tag_map), 1354 _klass(klass), 1355 _object_filter(object_filter), 1356 _heap_object_callback(heap_object_callback), 1357 _user_data(user_data), 1358 _iteration_aborted(false) 1359 { 1360 } 1361 1362 void do_object(oop o); 1363}; 1364 1365// invoked for each object in the heap 1366void IterateOverHeapObjectClosure::do_object(oop o) { 1367 // check if iteration has been halted 1368 if (is_iteration_aborted()) return; 1369 1370 // ignore any objects that aren't visible to profiler 1371 if (!ServiceUtil::visible_oop(o)) return; 1372 1373 // instanceof check when filtering by klass 1374 if (!klass().is_null() && !o->is_a(klass()())) { 1375 return; 1376 } 1377 // prepare for the calllback 1378 CallbackWrapper wrapper(tag_map(), o); 1379 1380 // if the object is tagged and we're only interested in untagged objects 1381 // then don't invoke the callback. Similiarly, if the object is untagged 1382 // and we're only interested in tagged objects we skip the callback. 1383 if (wrapper.obj_tag() != 0) { 1384 if (object_filter() == JVMTI_HEAP_OBJECT_UNTAGGED) return; 1385 } else { 1386 if (object_filter() == JVMTI_HEAP_OBJECT_TAGGED) return; 1387 } 1388 1389 // invoke the agent's callback 1390 jvmtiIterationControl control = (*object_callback())(wrapper.klass_tag(), 1391 wrapper.obj_size(), 1392 wrapper.obj_tag_p(), 1393 (void*)user_data()); 1394 if (control == JVMTI_ITERATION_ABORT) { 1395 set_iteration_aborted(true); 1396 } 1397} 1398 1399// An ObjectClosure used to support the IterateThroughHeap function 1400class IterateThroughHeapObjectClosure: public ObjectClosure { 1401 private: 1402 JvmtiTagMap* _tag_map; 1403 KlassHandle _klass; 1404 int _heap_filter; 1405 const jvmtiHeapCallbacks* _callbacks; 1406 const void* _user_data; 1407 1408 // accessor functions 1409 JvmtiTagMap* tag_map() const { return _tag_map; } 1410 int heap_filter() const { return _heap_filter; } 1411 const jvmtiHeapCallbacks* callbacks() const { return _callbacks; } 1412 KlassHandle klass() const { return _klass; } 1413 const void* user_data() const { return _user_data; } 1414 1415 // indicates if the iteration has been aborted 1416 bool _iteration_aborted; 1417 bool is_iteration_aborted() const { return _iteration_aborted; } 1418 1419 // used to check the visit control flags. If the abort flag is set 1420 // then we set the iteration aborted flag so that the iteration completes 1421 // without processing any further objects 1422 bool check_flags_for_abort(jint flags) { 1423 bool is_abort = (flags & JVMTI_VISIT_ABORT) != 0; 1424 if (is_abort) { 1425 _iteration_aborted = true; 1426 } 1427 return is_abort; 1428 } 1429 1430 public: 1431 IterateThroughHeapObjectClosure(JvmtiTagMap* tag_map, 1432 KlassHandle klass, 1433 int heap_filter, 1434 const jvmtiHeapCallbacks* heap_callbacks, 1435 const void* user_data) : 1436 _tag_map(tag_map), 1437 _klass(klass), 1438 _heap_filter(heap_filter), 1439 _callbacks(heap_callbacks), 1440 _user_data(user_data), 1441 _iteration_aborted(false) 1442 { 1443 } 1444 1445 void do_object(oop o); 1446}; 1447 1448// invoked for each object in the heap 1449void IterateThroughHeapObjectClosure::do_object(oop obj) { 1450 // check if iteration has been halted 1451 if (is_iteration_aborted()) return; 1452 1453 // ignore any objects that aren't visible to profiler 1454 if (!ServiceUtil::visible_oop(obj)) return; 1455 1456 // apply class filter 1457 if (is_filtered_by_klass_filter(obj, klass())) return; 1458 1459 // prepare for callback 1460 CallbackWrapper wrapper(tag_map(), obj); 1461 1462 // check if filtered by the heap filter 1463 if (is_filtered_by_heap_filter(wrapper.obj_tag(), wrapper.klass_tag(), heap_filter())) { 1464 return; 1465 } 1466 1467 // for arrays we need the length, otherwise -1 1468 bool is_array = obj->is_array(); 1469 int len = is_array ? arrayOop(obj)->length() : -1; 1470 1471 // invoke the object callback (if callback is provided) 1472 if (callbacks()->heap_iteration_callback != NULL) { 1473 jvmtiHeapIterationCallback cb = callbacks()->heap_iteration_callback; 1474 jint res = (*cb)(wrapper.klass_tag(), 1475 wrapper.obj_size(), 1476 wrapper.obj_tag_p(), 1477 (jint)len, 1478 (void*)user_data()); 1479 if (check_flags_for_abort(res)) return; 1480 } 1481 1482 // for objects and classes we report primitive fields if callback provided 1483 if (callbacks()->primitive_field_callback != NULL && obj->is_instance()) { 1484 jint res; 1485 jvmtiPrimitiveFieldCallback cb = callbacks()->primitive_field_callback; 1486 if (obj->klass() == SystemDictionary::class_klass()) { 1487 res = invoke_primitive_field_callback_for_static_fields(&wrapper, 1488 obj, 1489 cb, 1490 (void*)user_data()); 1491 } else { 1492 res = invoke_primitive_field_callback_for_instance_fields(&wrapper, 1493 obj, 1494 cb, 1495 (void*)user_data()); 1496 } 1497 if (check_flags_for_abort(res)) return; 1498 } 1499 1500 // string callback 1501 if (!is_array && 1502 callbacks()->string_primitive_value_callback != NULL && 1503 obj->klass() == SystemDictionary::string_klass()) { 1504 jint res = invoke_string_value_callback( 1505 callbacks()->string_primitive_value_callback, 1506 &wrapper, 1507 obj, 1508 (void*)user_data() ); 1509 if (check_flags_for_abort(res)) return; 1510 } 1511 1512 // array callback 1513 if (is_array && 1514 callbacks()->array_primitive_value_callback != NULL && 1515 obj->is_typeArray()) { 1516 jint res = invoke_array_primitive_value_callback( 1517 callbacks()->array_primitive_value_callback, 1518 &wrapper, 1519 obj, 1520 (void*)user_data() ); 1521 if (check_flags_for_abort(res)) return; 1522 } 1523}; 1524 1525 1526// Deprecated function to iterate over all objects in the heap 1527void JvmtiTagMap::iterate_over_heap(jvmtiHeapObjectFilter object_filter, 1528 KlassHandle klass, 1529 jvmtiHeapObjectCallback heap_object_callback, 1530 const void* user_data) 1531{ 1532 MutexLocker ml(Heap_lock); 1533 IterateOverHeapObjectClosure blk(this, 1534 klass, 1535 object_filter, 1536 heap_object_callback, 1537 user_data); 1538 VM_HeapIterateOperation op(&blk); 1539 VMThread::execute(&op); 1540} 1541 1542 1543// Iterates over all objects in the heap 1544void JvmtiTagMap::iterate_through_heap(jint heap_filter, 1545 KlassHandle klass, 1546 const jvmtiHeapCallbacks* callbacks, 1547 const void* user_data) 1548{ 1549 MutexLocker ml(Heap_lock); 1550 IterateThroughHeapObjectClosure blk(this, 1551 klass, 1552 heap_filter, 1553 callbacks, 1554 user_data); 1555 VM_HeapIterateOperation op(&blk); 1556 VMThread::execute(&op); 1557} 1558 1559// support class for get_objects_with_tags 1560 1561class TagObjectCollector : public JvmtiTagHashmapEntryClosure { 1562 private: 1563 JvmtiEnv* _env; 1564 jlong* _tags; 1565 jint _tag_count; 1566 1567 GrowableArray<jobject>* _object_results; // collected objects (JNI weak refs) 1568 GrowableArray<uint64_t>* _tag_results; // collected tags 1569 1570 public: 1571 TagObjectCollector(JvmtiEnv* env, const jlong* tags, jint tag_count) { 1572 _env = env; 1573 _tags = (jlong*)tags; 1574 _tag_count = tag_count; 1575 _object_results = new (ResourceObj::C_HEAP) GrowableArray<jobject>(1,true); 1576 _tag_results = new (ResourceObj::C_HEAP) GrowableArray<uint64_t>(1,true); 1577 } 1578 1579 ~TagObjectCollector() { 1580 delete _object_results; 1581 delete _tag_results; 1582 } 1583 1584 // for each tagged object check if the tag value matches 1585 // - if it matches then we create a JNI local reference to the object 1586 // and record the reference and tag value. 1587 // 1588 void do_entry(JvmtiTagHashmapEntry* entry) { 1589 for (int i=0; i<_tag_count; i++) { 1590 if (_tags[i] == entry->tag()) { 1591 oop o = JNIHandles::resolve(entry->object()); 1592 assert(o != NULL && o != JNIHandles::deleted_handle(), "sanity check"); 1593 1594 // the mirror is tagged 1595 if (o->is_klass()) { 1596 klassOop k = (klassOop)o; 1597 o = Klass::cast(k)->java_mirror(); 1598 } 1599 1600 jobject ref = JNIHandles::make_local(JavaThread::current(), o); 1601 _object_results->append(ref); 1602 _tag_results->append((uint64_t)entry->tag()); 1603 } 1604 } 1605 } 1606 1607 // return the results from the collection 1608 // 1609 jvmtiError result(jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) { 1610 jvmtiError error; 1611 int count = _object_results->length(); 1612 assert(count >= 0, "sanity check"); 1613 1614 // if object_result_ptr is not NULL then allocate the result and copy 1615 // in the object references. 1616 if (object_result_ptr != NULL) { 1617 error = _env->Allocate(count * sizeof(jobject), (unsigned char**)object_result_ptr); 1618 if (error != JVMTI_ERROR_NONE) { 1619 return error; 1620 } 1621 for (int i=0; i<count; i++) { 1622 (*object_result_ptr)[i] = _object_results->at(i); 1623 } 1624 } 1625 1626 // if tag_result_ptr is not NULL then allocate the result and copy 1627 // in the tag values. 1628 if (tag_result_ptr != NULL) { 1629 error = _env->Allocate(count * sizeof(jlong), (unsigned char**)tag_result_ptr); 1630 if (error != JVMTI_ERROR_NONE) { 1631 if (object_result_ptr != NULL) { 1632 _env->Deallocate((unsigned char*)object_result_ptr); 1633 } 1634 return error; 1635 } 1636 for (int i=0; i<count; i++) { 1637 (*tag_result_ptr)[i] = (jlong)_tag_results->at(i); 1638 } 1639 } 1640 1641 *count_ptr = count; 1642 return JVMTI_ERROR_NONE; 1643 } 1644}; 1645 1646// return the list of objects with the specified tags 1647jvmtiError JvmtiTagMap::get_objects_with_tags(const jlong* tags, 1648 jint count, jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) { 1649 1650 TagObjectCollector collector(env(), tags, count); 1651 { 1652 // iterate over all tagged objects 1653 MutexLocker ml(lock()); 1654 entry_iterate(&collector); 1655 } 1656 return collector.result(count_ptr, object_result_ptr, tag_result_ptr); 1657} 1658 1659 1660// ObjectMarker is used to support the marking objects when walking the 1661// heap. 1662// 1663// This implementation uses the existing mark bits in an object for 1664// marking. Objects that are marked must later have their headers restored. 1665// As most objects are unlocked and don't have their identity hash computed 1666// we don't have to save their headers. Instead we save the headers that 1667// are "interesting". Later when the headers are restored this implementation 1668// restores all headers to their initial value and then restores the few 1669// objects that had interesting headers. 1670// 1671// Future work: This implementation currently uses growable arrays to save 1672// the oop and header of interesting objects. As an optimization we could 1673// use the same technique as the GC and make use of the unused area 1674// between top() and end(). 1675// 1676 1677// An ObjectClosure used to restore the mark bits of an object 1678class RestoreMarksClosure : public ObjectClosure { 1679 public: 1680 void do_object(oop o) { 1681 if (o != NULL) { 1682 markOop mark = o->mark(); 1683 if (mark->is_marked()) { 1684 o->init_mark(); 1685 } 1686 } 1687 } 1688}; 1689 1690// ObjectMarker provides the mark and visited functions 1691class ObjectMarker : AllStatic { 1692 private: 1693 // saved headers 1694 static GrowableArray<oop>* _saved_oop_stack; 1695 static GrowableArray<markOop>* _saved_mark_stack; 1696 1697 public: 1698 static void init(); // initialize 1699 static void done(); // clean-up 1700 1701 static inline void mark(oop o); // mark an object 1702 static inline bool visited(oop o); // check if object has been visited 1703}; 1704 1705GrowableArray<oop>* ObjectMarker::_saved_oop_stack = NULL; 1706GrowableArray<markOop>* ObjectMarker::_saved_mark_stack = NULL; 1707 1708// initialize ObjectMarker - prepares for object marking 1709void ObjectMarker::init() { 1710 assert(Thread::current()->is_VM_thread(), "must be VMThread"); 1711 1712 // prepare heap for iteration 1713 Universe::heap()->ensure_parsability(false); // no need to retire TLABs 1714 1715 // create stacks for interesting headers 1716 _saved_mark_stack = new (ResourceObj::C_HEAP) GrowableArray<markOop>(4000, true); 1717 _saved_oop_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(4000, true); 1718 1719 if (UseBiasedLocking) { 1720 BiasedLocking::preserve_marks(); 1721 } 1722} 1723 1724// Object marking is done so restore object headers 1725void ObjectMarker::done() { 1726 // iterate over all objects and restore the mark bits to 1727 // their initial value 1728 RestoreMarksClosure blk; 1729 Universe::heap()->object_iterate(&blk); 1730 1731 // When sharing is enabled we need to restore the headers of the objects 1732 // in the readwrite space too. 1733 if (UseSharedSpaces) { 1734 GenCollectedHeap* gch = GenCollectedHeap::heap(); 1735 CompactingPermGenGen* gen = (CompactingPermGenGen*)gch->perm_gen(); 1736 gen->rw_space()->object_iterate(&blk); 1737 } 1738 1739 // now restore the interesting headers 1740 for (int i = 0; i < _saved_oop_stack->length(); i++) { 1741 oop o = _saved_oop_stack->at(i); 1742 markOop mark = _saved_mark_stack->at(i); 1743 o->set_mark(mark); 1744 } 1745 1746 if (UseBiasedLocking) { 1747 BiasedLocking::restore_marks(); 1748 } 1749 1750 // free the stacks 1751 delete _saved_oop_stack; 1752 delete _saved_mark_stack; 1753} 1754 1755// mark an object 1756inline void ObjectMarker::mark(oop o) { 1757 assert(Universe::heap()->is_in(o), "sanity check"); 1758 assert(!o->mark()->is_marked(), "should only mark an object once"); 1759 1760 // object's mark word 1761 markOop mark = o->mark(); 1762 1763 if (mark->must_be_preserved(o)) { 1764 _saved_mark_stack->push(mark); 1765 _saved_oop_stack->push(o); 1766 } 1767 1768 // mark the object 1769 o->set_mark(markOopDesc::prototype()->set_marked()); 1770} 1771 1772// return true if object is marked 1773inline bool ObjectMarker::visited(oop o) { 1774 return o->mark()->is_marked(); 1775} 1776 1777// Stack allocated class to help ensure that ObjectMarker is used 1778// correctly. Constructor initializes ObjectMarker, destructor calls 1779// ObjectMarker's done() function to restore object headers. 1780class ObjectMarkerController : public StackObj { 1781 public: 1782 ObjectMarkerController() { 1783 ObjectMarker::init(); 1784 } 1785 ~ObjectMarkerController() { 1786 ObjectMarker::done(); 1787 } 1788}; 1789 1790 1791// helper to map a jvmtiHeapReferenceKind to an old style jvmtiHeapRootKind 1792// (not performance critical as only used for roots) 1793static jvmtiHeapRootKind toJvmtiHeapRootKind(jvmtiHeapReferenceKind kind) { 1794 switch (kind) { 1795 case JVMTI_HEAP_REFERENCE_JNI_GLOBAL: return JVMTI_HEAP_ROOT_JNI_GLOBAL; 1796 case JVMTI_HEAP_REFERENCE_SYSTEM_CLASS: return JVMTI_HEAP_ROOT_SYSTEM_CLASS; 1797 case JVMTI_HEAP_REFERENCE_MONITOR: return JVMTI_HEAP_ROOT_MONITOR; 1798 case JVMTI_HEAP_REFERENCE_STACK_LOCAL: return JVMTI_HEAP_ROOT_STACK_LOCAL; 1799 case JVMTI_HEAP_REFERENCE_JNI_LOCAL: return JVMTI_HEAP_ROOT_JNI_LOCAL; 1800 case JVMTI_HEAP_REFERENCE_THREAD: return JVMTI_HEAP_ROOT_THREAD; 1801 case JVMTI_HEAP_REFERENCE_OTHER: return JVMTI_HEAP_ROOT_OTHER; 1802 default: ShouldNotReachHere(); return JVMTI_HEAP_ROOT_OTHER; 1803 } 1804} 1805 1806// Base class for all heap walk contexts. The base class maintains a flag 1807// to indicate if the context is valid or not. 1808class HeapWalkContext VALUE_OBJ_CLASS_SPEC { 1809 private: 1810 bool _valid; 1811 public: 1812 HeapWalkContext(bool valid) { _valid = valid; } 1813 void invalidate() { _valid = false; } 1814 bool is_valid() const { return _valid; } 1815}; 1816 1817// A basic heap walk context for the deprecated heap walking functions. 1818// The context for a basic heap walk are the callbacks and fields used by 1819// the referrer caching scheme. 1820class BasicHeapWalkContext: public HeapWalkContext { 1821 private: 1822 jvmtiHeapRootCallback _heap_root_callback; 1823 jvmtiStackReferenceCallback _stack_ref_callback; 1824 jvmtiObjectReferenceCallback _object_ref_callback; 1825 1826 // used for caching 1827 oop _last_referrer; 1828 jlong _last_referrer_tag; 1829 1830 public: 1831 BasicHeapWalkContext() : HeapWalkContext(false) { } 1832 1833 BasicHeapWalkContext(jvmtiHeapRootCallback heap_root_callback, 1834 jvmtiStackReferenceCallback stack_ref_callback, 1835 jvmtiObjectReferenceCallback object_ref_callback) : 1836 HeapWalkContext(true), 1837 _heap_root_callback(heap_root_callback), 1838 _stack_ref_callback(stack_ref_callback), 1839 _object_ref_callback(object_ref_callback), 1840 _last_referrer(NULL), 1841 _last_referrer_tag(0) { 1842 } 1843 1844 // accessors 1845 jvmtiHeapRootCallback heap_root_callback() const { return _heap_root_callback; } 1846 jvmtiStackReferenceCallback stack_ref_callback() const { return _stack_ref_callback; } 1847 jvmtiObjectReferenceCallback object_ref_callback() const { return _object_ref_callback; } 1848 1849 oop last_referrer() const { return _last_referrer; } 1850 void set_last_referrer(oop referrer) { _last_referrer = referrer; } 1851 jlong last_referrer_tag() const { return _last_referrer_tag; } 1852 void set_last_referrer_tag(jlong value) { _last_referrer_tag = value; } 1853}; 1854 1855// The advanced heap walk context for the FollowReferences functions. 1856// The context is the callbacks, and the fields used for filtering. 1857class AdvancedHeapWalkContext: public HeapWalkContext { 1858 private: 1859 jint _heap_filter; 1860 KlassHandle _klass_filter; 1861 const jvmtiHeapCallbacks* _heap_callbacks; 1862 1863 public: 1864 AdvancedHeapWalkContext() : HeapWalkContext(false) { } 1865 1866 AdvancedHeapWalkContext(jint heap_filter, 1867 KlassHandle klass_filter, 1868 const jvmtiHeapCallbacks* heap_callbacks) : 1869 HeapWalkContext(true), 1870 _heap_filter(heap_filter), 1871 _klass_filter(klass_filter), 1872 _heap_callbacks(heap_callbacks) { 1873 } 1874 1875 // accessors 1876 jint heap_filter() const { return _heap_filter; } 1877 KlassHandle klass_filter() const { return _klass_filter; } 1878 1879 const jvmtiHeapReferenceCallback heap_reference_callback() const { 1880 return _heap_callbacks->heap_reference_callback; 1881 }; 1882 const jvmtiPrimitiveFieldCallback primitive_field_callback() const { 1883 return _heap_callbacks->primitive_field_callback; 1884 } 1885 const jvmtiArrayPrimitiveValueCallback array_primitive_value_callback() const { 1886 return _heap_callbacks->array_primitive_value_callback; 1887 } 1888 const jvmtiStringPrimitiveValueCallback string_primitive_value_callback() const { 1889 return _heap_callbacks->string_primitive_value_callback; 1890 } 1891}; 1892 1893// The CallbackInvoker is a class with static functions that the heap walk can call 1894// into to invoke callbacks. It works in one of two modes. The "basic" mode is 1895// used for the deprecated IterateOverReachableObjects functions. The "advanced" 1896// mode is for the newer FollowReferences function which supports a lot of 1897// additional callbacks. 1898class CallbackInvoker : AllStatic { 1899 private: 1900 // heap walk styles 1901 enum { basic, advanced }; 1902 static int _heap_walk_type; 1903 static bool is_basic_heap_walk() { return _heap_walk_type == basic; } 1904 static bool is_advanced_heap_walk() { return _heap_walk_type == advanced; } 1905 1906 // context for basic style heap walk 1907 static BasicHeapWalkContext _basic_context; 1908 static BasicHeapWalkContext* basic_context() { 1909 assert(_basic_context.is_valid(), "invalid"); 1910 return &_basic_context; 1911 } 1912 1913 // context for advanced style heap walk 1914 static AdvancedHeapWalkContext _advanced_context; 1915 static AdvancedHeapWalkContext* advanced_context() { 1916 assert(_advanced_context.is_valid(), "invalid"); 1917 return &_advanced_context; 1918 } 1919 1920 // context needed for all heap walks 1921 static JvmtiTagMap* _tag_map; 1922 static const void* _user_data; 1923 static GrowableArray<oop>* _visit_stack; 1924 1925 // accessors 1926 static JvmtiTagMap* tag_map() { return _tag_map; } 1927 static const void* user_data() { return _user_data; } 1928 static GrowableArray<oop>* visit_stack() { return _visit_stack; } 1929 1930 // if the object hasn't been visited then push it onto the visit stack 1931 // so that it will be visited later 1932 static inline bool check_for_visit(oop obj) { 1933 if (!ObjectMarker::visited(obj)) visit_stack()->push(obj); 1934 return true; 1935 } 1936 1937 // invoke basic style callbacks 1938 static inline bool invoke_basic_heap_root_callback 1939 (jvmtiHeapRootKind root_kind, oop obj); 1940 static inline bool invoke_basic_stack_ref_callback 1941 (jvmtiHeapRootKind root_kind, jlong thread_tag, jint depth, jmethodID method, 1942 int slot, oop obj); 1943 static inline bool invoke_basic_object_reference_callback 1944 (jvmtiObjectReferenceKind ref_kind, oop referrer, oop referree, jint index); 1945 1946 // invoke advanced style callbacks 1947 static inline bool invoke_advanced_heap_root_callback 1948 (jvmtiHeapReferenceKind ref_kind, oop obj); 1949 static inline bool invoke_advanced_stack_ref_callback 1950 (jvmtiHeapReferenceKind ref_kind, jlong thread_tag, jlong tid, int depth, 1951 jmethodID method, jlocation bci, jint slot, oop obj); 1952 static inline bool invoke_advanced_object_reference_callback 1953 (jvmtiHeapReferenceKind ref_kind, oop referrer, oop referree, jint index); 1954 1955 // used to report the value of primitive fields 1956 static inline bool report_primitive_field 1957 (jvmtiHeapReferenceKind ref_kind, oop obj, jint index, address addr, char type); 1958 1959 public: 1960 // initialize for basic mode 1961 static void initialize_for_basic_heap_walk(JvmtiTagMap* tag_map, 1962 GrowableArray<oop>* visit_stack, 1963 const void* user_data, 1964 BasicHeapWalkContext context); 1965 1966 // initialize for advanced mode 1967 static void initialize_for_advanced_heap_walk(JvmtiTagMap* tag_map, 1968 GrowableArray<oop>* visit_stack, 1969 const void* user_data, 1970 AdvancedHeapWalkContext context); 1971 1972 // functions to report roots 1973 static inline bool report_simple_root(jvmtiHeapReferenceKind kind, oop o); 1974 static inline bool report_jni_local_root(jlong thread_tag, jlong tid, jint depth, 1975 jmethodID m, oop o); 1976 static inline bool report_stack_ref_root(jlong thread_tag, jlong tid, jint depth, 1977 jmethodID method, jlocation bci, jint slot, oop o); 1978 1979 // functions to report references 1980 static inline bool report_array_element_reference(oop referrer, oop referree, jint index); 1981 static inline bool report_class_reference(oop referrer, oop referree); 1982 static inline bool report_class_loader_reference(oop referrer, oop referree); 1983 static inline bool report_signers_reference(oop referrer, oop referree); 1984 static inline bool report_protection_domain_reference(oop referrer, oop referree); 1985 static inline bool report_superclass_reference(oop referrer, oop referree); 1986 static inline bool report_interface_reference(oop referrer, oop referree); 1987 static inline bool report_static_field_reference(oop referrer, oop referree, jint slot); 1988 static inline bool report_field_reference(oop referrer, oop referree, jint slot); 1989 static inline bool report_constant_pool_reference(oop referrer, oop referree, jint index); 1990 static inline bool report_primitive_array_values(oop array); 1991 static inline bool report_string_value(oop str); 1992 static inline bool report_primitive_instance_field(oop o, jint index, address value, char type); 1993 static inline bool report_primitive_static_field(oop o, jint index, address value, char type); 1994}; 1995 1996// statics 1997int CallbackInvoker::_heap_walk_type; 1998BasicHeapWalkContext CallbackInvoker::_basic_context; 1999AdvancedHeapWalkContext CallbackInvoker::_advanced_context; 2000JvmtiTagMap* CallbackInvoker::_tag_map; 2001const void* CallbackInvoker::_user_data; 2002GrowableArray<oop>* CallbackInvoker::_visit_stack; 2003 2004// initialize for basic heap walk (IterateOverReachableObjects et al) 2005void CallbackInvoker::initialize_for_basic_heap_walk(JvmtiTagMap* tag_map, 2006 GrowableArray<oop>* visit_stack, 2007 const void* user_data, 2008 BasicHeapWalkContext context) { 2009 _tag_map = tag_map; 2010 _visit_stack = visit_stack; 2011 _user_data = user_data; 2012 _basic_context = context; 2013 _advanced_context.invalidate(); // will trigger assertion if used 2014 _heap_walk_type = basic; 2015} 2016 2017// initialize for advanced heap walk (FollowReferences) 2018void CallbackInvoker::initialize_for_advanced_heap_walk(JvmtiTagMap* tag_map, 2019 GrowableArray<oop>* visit_stack, 2020 const void* user_data, 2021 AdvancedHeapWalkContext context) { 2022 _tag_map = tag_map; 2023 _visit_stack = visit_stack; 2024 _user_data = user_data; 2025 _advanced_context = context; 2026 _basic_context.invalidate(); // will trigger assertion if used 2027 _heap_walk_type = advanced; 2028} 2029 2030 2031// invoke basic style heap root callback 2032inline bool CallbackInvoker::invoke_basic_heap_root_callback(jvmtiHeapRootKind root_kind, oop obj) { 2033 assert(ServiceUtil::visible_oop(obj), "checking"); 2034 2035 // if we heap roots should be reported 2036 jvmtiHeapRootCallback cb = basic_context()->heap_root_callback(); 2037 if (cb == NULL) { 2038 return check_for_visit(obj); 2039 } 2040 2041 CallbackWrapper wrapper(tag_map(), obj); 2042 jvmtiIterationControl control = (*cb)(root_kind, 2043 wrapper.klass_tag(), 2044 wrapper.obj_size(), 2045 wrapper.obj_tag_p(), 2046 (void*)user_data()); 2047 // push root to visit stack when following references 2048 if (control == JVMTI_ITERATION_CONTINUE && 2049 basic_context()->object_ref_callback() != NULL) { 2050 visit_stack()->push(obj); 2051 } 2052 return control != JVMTI_ITERATION_ABORT; 2053} 2054 2055// invoke basic style stack ref callback 2056inline bool CallbackInvoker::invoke_basic_stack_ref_callback(jvmtiHeapRootKind root_kind, 2057 jlong thread_tag, 2058 jint depth, 2059 jmethodID method, 2060 jint slot, 2061 oop obj) { 2062 assert(ServiceUtil::visible_oop(obj), "checking"); 2063 2064 // if we stack refs should be reported 2065 jvmtiStackReferenceCallback cb = basic_context()->stack_ref_callback(); 2066 if (cb == NULL) { 2067 return check_for_visit(obj); 2068 } 2069 2070 CallbackWrapper wrapper(tag_map(), obj); 2071 jvmtiIterationControl control = (*cb)(root_kind, 2072 wrapper.klass_tag(), 2073 wrapper.obj_size(), 2074 wrapper.obj_tag_p(), 2075 thread_tag, 2076 depth, 2077 method, 2078 slot, 2079 (void*)user_data()); 2080 // push root to visit stack when following references 2081 if (control == JVMTI_ITERATION_CONTINUE && 2082 basic_context()->object_ref_callback() != NULL) { 2083 visit_stack()->push(obj); 2084 } 2085 return control != JVMTI_ITERATION_ABORT; 2086} 2087 2088// invoke basic style object reference callback 2089inline bool CallbackInvoker::invoke_basic_object_reference_callback(jvmtiObjectReferenceKind ref_kind, 2090 oop referrer, 2091 oop referree, 2092 jint index) { 2093 2094 assert(ServiceUtil::visible_oop(referrer), "checking"); 2095 assert(ServiceUtil::visible_oop(referree), "checking"); 2096 2097 BasicHeapWalkContext* context = basic_context(); 2098 2099 // callback requires the referrer's tag. If it's the same referrer 2100 // as the last call then we use the cached value. 2101 jlong referrer_tag; 2102 if (referrer == context->last_referrer()) { 2103 referrer_tag = context->last_referrer_tag(); 2104 } else { 2105 referrer_tag = tag_for(tag_map(), klassOop_if_java_lang_Class(referrer)); 2106 } 2107 2108 // do the callback 2109 CallbackWrapper wrapper(tag_map(), referree); 2110 jvmtiObjectReferenceCallback cb = context->object_ref_callback(); 2111 jvmtiIterationControl control = (*cb)(ref_kind, 2112 wrapper.klass_tag(), 2113 wrapper.obj_size(), 2114 wrapper.obj_tag_p(), 2115 referrer_tag, 2116 index, 2117 (void*)user_data()); 2118 2119 // record referrer and referrer tag. For self-references record the 2120 // tag value from the callback as this might differ from referrer_tag. 2121 context->set_last_referrer(referrer); 2122 if (referrer == referree) { 2123 context->set_last_referrer_tag(*wrapper.obj_tag_p()); 2124 } else { 2125 context->set_last_referrer_tag(referrer_tag); 2126 } 2127 2128 if (control == JVMTI_ITERATION_CONTINUE) { 2129 return check_for_visit(referree); 2130 } else { 2131 return control != JVMTI_ITERATION_ABORT; 2132 } 2133} 2134 2135// invoke advanced style heap root callback 2136inline bool CallbackInvoker::invoke_advanced_heap_root_callback(jvmtiHeapReferenceKind ref_kind, 2137 oop obj) { 2138 assert(ServiceUtil::visible_oop(obj), "checking"); 2139 2140 AdvancedHeapWalkContext* context = advanced_context(); 2141 2142 // check that callback is provided 2143 jvmtiHeapReferenceCallback cb = context->heap_reference_callback(); 2144 if (cb == NULL) { 2145 return check_for_visit(obj); 2146 } 2147 2148 // apply class filter 2149 if (is_filtered_by_klass_filter(obj, context->klass_filter())) { 2150 return check_for_visit(obj); 2151 } 2152 2153 // setup the callback wrapper 2154 CallbackWrapper wrapper(tag_map(), obj); 2155 2156 // apply tag filter 2157 if (is_filtered_by_heap_filter(wrapper.obj_tag(), 2158 wrapper.klass_tag(), 2159 context->heap_filter())) { 2160 return check_for_visit(obj); 2161 } 2162 2163 // for arrays we need the length, otherwise -1 2164 jint len = (jint)(obj->is_array() ? arrayOop(obj)->length() : -1); 2165 2166 // invoke the callback 2167 jint res = (*cb)(ref_kind, 2168 NULL, // referrer info 2169 wrapper.klass_tag(), 2170 0, // referrer_class_tag is 0 for heap root 2171 wrapper.obj_size(), 2172 wrapper.obj_tag_p(), 2173 NULL, // referrer_tag_p 2174 len, 2175 (void*)user_data()); 2176 if (res & JVMTI_VISIT_ABORT) { 2177 return false;// referrer class tag 2178 } 2179 if (res & JVMTI_VISIT_OBJECTS) { 2180 check_for_visit(obj); 2181 } 2182 return true; 2183} 2184 2185// report a reference from a thread stack to an object 2186inline bool CallbackInvoker::invoke_advanced_stack_ref_callback(jvmtiHeapReferenceKind ref_kind, 2187 jlong thread_tag, 2188 jlong tid, 2189 int depth, 2190 jmethodID method, 2191 jlocation bci, 2192 jint slot, 2193 oop obj) { 2194 assert(ServiceUtil::visible_oop(obj), "checking"); 2195 2196 AdvancedHeapWalkContext* context = advanced_context(); 2197 2198 // check that callback is provider 2199 jvmtiHeapReferenceCallback cb = context->heap_reference_callback(); 2200 if (cb == NULL) { 2201 return check_for_visit(obj); 2202 } 2203 2204 // apply class filter 2205 if (is_filtered_by_klass_filter(obj, context->klass_filter())) { 2206 return check_for_visit(obj); 2207 } 2208 2209 // setup the callback wrapper 2210 CallbackWrapper wrapper(tag_map(), obj); 2211 2212 // apply tag filter 2213 if (is_filtered_by_heap_filter(wrapper.obj_tag(), 2214 wrapper.klass_tag(), 2215 context->heap_filter())) { 2216 return check_for_visit(obj); 2217 } 2218 2219 // setup the referrer info 2220 jvmtiHeapReferenceInfo reference_info; 2221 reference_info.stack_local.thread_tag = thread_tag; 2222 reference_info.stack_local.thread_id = tid; 2223 reference_info.stack_local.depth = depth; 2224 reference_info.stack_local.method = method; 2225 reference_info.stack_local.location = bci; 2226 reference_info.stack_local.slot = slot; 2227 2228 // for arrays we need the length, otherwise -1 2229 jint len = (jint)(obj->is_array() ? arrayOop(obj)->length() : -1); 2230 2231 // call into the agent 2232 int res = (*cb)(ref_kind, 2233 &reference_info, 2234 wrapper.klass_tag(), 2235 0, // referrer_class_tag is 0 for heap root (stack) 2236 wrapper.obj_size(), 2237 wrapper.obj_tag_p(), 2238 NULL, // referrer_tag is 0 for root 2239 len, 2240 (void*)user_data()); 2241 2242 if (res & JVMTI_VISIT_ABORT) { 2243 return false; 2244 } 2245 if (res & JVMTI_VISIT_OBJECTS) { 2246 check_for_visit(obj); 2247 } 2248 return true; 2249} 2250 2251// This mask is used to pass reference_info to a jvmtiHeapReferenceCallback 2252// only for ref_kinds defined by the JVM TI spec. Otherwise, NULL is passed. 2253#define REF_INFO_MASK ((1 << JVMTI_HEAP_REFERENCE_FIELD) \ 2254 | (1 << JVMTI_HEAP_REFERENCE_STATIC_FIELD) \ 2255 | (1 << JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT) \ 2256 | (1 << JVMTI_HEAP_REFERENCE_CONSTANT_POOL) \ 2257 | (1 << JVMTI_HEAP_REFERENCE_STACK_LOCAL) \ 2258 | (1 << JVMTI_HEAP_REFERENCE_JNI_LOCAL)) 2259 2260// invoke the object reference callback to report a reference 2261inline bool CallbackInvoker::invoke_advanced_object_reference_callback(jvmtiHeapReferenceKind ref_kind, 2262 oop referrer, 2263 oop obj, 2264 jint index) 2265{ 2266 // field index is only valid field in reference_info 2267 static jvmtiHeapReferenceInfo reference_info = { 0 }; 2268 2269 assert(ServiceUtil::visible_oop(referrer), "checking"); 2270 assert(ServiceUtil::visible_oop(obj), "checking"); 2271 2272 AdvancedHeapWalkContext* context = advanced_context(); 2273 2274 // check that callback is provider 2275 jvmtiHeapReferenceCallback cb = context->heap_reference_callback(); 2276 if (cb == NULL) { 2277 return check_for_visit(obj); 2278 } 2279 2280 // apply class filter 2281 if (is_filtered_by_klass_filter(obj, context->klass_filter())) { 2282 return check_for_visit(obj); 2283 } 2284 2285 // setup the callback wrapper 2286 TwoOopCallbackWrapper wrapper(tag_map(), referrer, obj); 2287 2288 // apply tag filter 2289 if (is_filtered_by_heap_filter(wrapper.obj_tag(), 2290 wrapper.klass_tag(), 2291 context->heap_filter())) { 2292 return check_for_visit(obj); 2293 } 2294 2295 // field index is only valid field in reference_info 2296 reference_info.field.index = index; 2297 2298 // for arrays we need the length, otherwise -1 2299 jint len = (jint)(obj->is_array() ? arrayOop(obj)->length() : -1); 2300 2301 // invoke the callback 2302 int res = (*cb)(ref_kind, 2303 (REF_INFO_MASK & (1 << ref_kind)) ? &reference_info : NULL, 2304 wrapper.klass_tag(), 2305 wrapper.referrer_klass_tag(), 2306 wrapper.obj_size(), 2307 wrapper.obj_tag_p(), 2308 wrapper.referrer_tag_p(), 2309 len, 2310 (void*)user_data()); 2311 2312 if (res & JVMTI_VISIT_ABORT) { 2313 return false; 2314 } 2315 if (res & JVMTI_VISIT_OBJECTS) { 2316 check_for_visit(obj); 2317 } 2318 return true; 2319} 2320 2321// report a "simple root" 2322inline bool CallbackInvoker::report_simple_root(jvmtiHeapReferenceKind kind, oop obj) { 2323 assert(kind != JVMTI_HEAP_REFERENCE_STACK_LOCAL && 2324 kind != JVMTI_HEAP_REFERENCE_JNI_LOCAL, "not a simple root"); 2325 assert(ServiceUtil::visible_oop(obj), "checking"); 2326 2327 if (is_basic_heap_walk()) { 2328 // map to old style root kind 2329 jvmtiHeapRootKind root_kind = toJvmtiHeapRootKind(kind); 2330 return invoke_basic_heap_root_callback(root_kind, obj); 2331 } else { 2332 assert(is_advanced_heap_walk(), "wrong heap walk type"); 2333 return invoke_advanced_heap_root_callback(kind, obj); 2334 } 2335} 2336 2337 2338// invoke the primitive array values 2339inline bool CallbackInvoker::report_primitive_array_values(oop obj) { 2340 assert(obj->is_typeArray(), "not a primitive array"); 2341 2342 AdvancedHeapWalkContext* context = advanced_context(); 2343 assert(context->array_primitive_value_callback() != NULL, "no callback"); 2344 2345 // apply class filter 2346 if (is_filtered_by_klass_filter(obj, context->klass_filter())) { 2347 return true; 2348 } 2349 2350 CallbackWrapper wrapper(tag_map(), obj); 2351 2352 // apply tag filter 2353 if (is_filtered_by_heap_filter(wrapper.obj_tag(), 2354 wrapper.klass_tag(), 2355 context->heap_filter())) { 2356 return true; 2357 } 2358 2359 // invoke the callback 2360 int res = invoke_array_primitive_value_callback(context->array_primitive_value_callback(), 2361 &wrapper, 2362 obj, 2363 (void*)user_data()); 2364 return (!(res & JVMTI_VISIT_ABORT)); 2365} 2366 2367// invoke the string value callback 2368inline bool CallbackInvoker::report_string_value(oop str) { 2369 assert(str->klass() == SystemDictionary::string_klass(), "not a string"); 2370 2371 AdvancedHeapWalkContext* context = advanced_context(); 2372 assert(context->string_primitive_value_callback() != NULL, "no callback"); 2373 2374 // apply class filter 2375 if (is_filtered_by_klass_filter(str, context->klass_filter())) { 2376 return true; 2377 } 2378 2379 CallbackWrapper wrapper(tag_map(), str); 2380 2381 // apply tag filter 2382 if (is_filtered_by_heap_filter(wrapper.obj_tag(), 2383 wrapper.klass_tag(), 2384 context->heap_filter())) { 2385 return true; 2386 } 2387 2388 // invoke the callback 2389 int res = invoke_string_value_callback(context->string_primitive_value_callback(), 2390 &wrapper, 2391 str, 2392 (void*)user_data()); 2393 return (!(res & JVMTI_VISIT_ABORT)); 2394} 2395 2396// invoke the primitive field callback 2397inline bool CallbackInvoker::report_primitive_field(jvmtiHeapReferenceKind ref_kind, 2398 oop obj, 2399 jint index, 2400 address addr, 2401 char type) 2402{ 2403 // for primitive fields only the index will be set 2404 static jvmtiHeapReferenceInfo reference_info = { 0 }; 2405 2406 AdvancedHeapWalkContext* context = advanced_context(); 2407 assert(context->primitive_field_callback() != NULL, "no callback"); 2408 2409 // apply class filter 2410 if (is_filtered_by_klass_filter(obj, context->klass_filter())) { 2411 return true; 2412 } 2413 2414 CallbackWrapper wrapper(tag_map(), obj); 2415 2416 // apply tag filter 2417 if (is_filtered_by_heap_filter(wrapper.obj_tag(), 2418 wrapper.klass_tag(), 2419 context->heap_filter())) { 2420 return true; 2421 } 2422 2423 // the field index in the referrer 2424 reference_info.field.index = index; 2425 2426 // map the type 2427 jvmtiPrimitiveType value_type = (jvmtiPrimitiveType)type; 2428 2429 // setup the jvalue 2430 jvalue value; 2431 copy_to_jvalue(&value, addr, value_type); 2432 2433 jvmtiPrimitiveFieldCallback cb = context->primitive_field_callback(); 2434 int res = (*cb)(ref_kind, 2435 &reference_info, 2436 wrapper.klass_tag(), 2437 wrapper.obj_tag_p(), 2438 value, 2439 value_type, 2440 (void*)user_data()); 2441 return (!(res & JVMTI_VISIT_ABORT)); 2442} 2443 2444 2445// instance field 2446inline bool CallbackInvoker::report_primitive_instance_field(oop obj, 2447 jint index, 2448 address value, 2449 char type) { 2450 return report_primitive_field(JVMTI_HEAP_REFERENCE_FIELD, 2451 obj, 2452 index, 2453 value, 2454 type); 2455} 2456 2457// static field 2458inline bool CallbackInvoker::report_primitive_static_field(oop obj, 2459 jint index, 2460 address value, 2461 char type) { 2462 return report_primitive_field(JVMTI_HEAP_REFERENCE_STATIC_FIELD, 2463 obj, 2464 index, 2465 value, 2466 type); 2467} 2468 2469// report a JNI local (root object) to the profiler 2470inline bool CallbackInvoker::report_jni_local_root(jlong thread_tag, jlong tid, jint depth, jmethodID m, oop obj) { 2471 if (is_basic_heap_walk()) { 2472 return invoke_basic_stack_ref_callback(JVMTI_HEAP_ROOT_JNI_LOCAL, 2473 thread_tag, 2474 depth, 2475 m, 2476 -1, 2477 obj); 2478 } else { 2479 return invoke_advanced_stack_ref_callback(JVMTI_HEAP_REFERENCE_JNI_LOCAL, 2480 thread_tag, tid, 2481 depth, 2482 m, 2483 (jlocation)-1, 2484 -1, 2485 obj); 2486 } 2487} 2488 2489 2490// report a local (stack reference, root object) 2491inline bool CallbackInvoker::report_stack_ref_root(jlong thread_tag, 2492 jlong tid, 2493 jint depth, 2494 jmethodID method, 2495 jlocation bci, 2496 jint slot, 2497 oop obj) { 2498 if (is_basic_heap_walk()) { 2499 return invoke_basic_stack_ref_callback(JVMTI_HEAP_ROOT_STACK_LOCAL, 2500 thread_tag, 2501 depth, 2502 method, 2503 slot, 2504 obj); 2505 } else { 2506 return invoke_advanced_stack_ref_callback(JVMTI_HEAP_REFERENCE_STACK_LOCAL, 2507 thread_tag, 2508 tid, 2509 depth, 2510 method, 2511 bci, 2512 slot, 2513 obj); 2514 } 2515} 2516 2517// report an object referencing a class. 2518inline bool CallbackInvoker::report_class_reference(oop referrer, oop referree) { 2519 if (is_basic_heap_walk()) { 2520 return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CLASS, referrer, referree, -1); 2521 } else { 2522 return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_CLASS, referrer, referree, -1); 2523 } 2524} 2525 2526// report a class referencing its class loader. 2527inline bool CallbackInvoker::report_class_loader_reference(oop referrer, oop referree) { 2528 if (is_basic_heap_walk()) { 2529 return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CLASS_LOADER, referrer, referree, -1); 2530 } else { 2531 return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_CLASS_LOADER, referrer, referree, -1); 2532 } 2533} 2534 2535// report a class referencing its signers. 2536inline bool CallbackInvoker::report_signers_reference(oop referrer, oop referree) { 2537 if (is_basic_heap_walk()) { 2538 return invoke_basic_object_reference_callback(JVMTI_REFERENCE_SIGNERS, referrer, referree, -1); 2539 } else { 2540 return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_SIGNERS, referrer, referree, -1); 2541 } 2542} 2543 2544// report a class referencing its protection domain.. 2545inline bool CallbackInvoker::report_protection_domain_reference(oop referrer, oop referree) { 2546 if (is_basic_heap_walk()) { 2547 return invoke_basic_object_reference_callback(JVMTI_REFERENCE_PROTECTION_DOMAIN, referrer, referree, -1); 2548 } else { 2549 return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN, referrer, referree, -1); 2550 } 2551} 2552 2553// report a class referencing its superclass. 2554inline bool CallbackInvoker::report_superclass_reference(oop referrer, oop referree) { 2555 if (is_basic_heap_walk()) { 2556 // Send this to be consistent with past implementation 2557 return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CLASS, referrer, referree, -1); 2558 } else { 2559 return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_SUPERCLASS, referrer, referree, -1); 2560 } 2561} 2562 2563// report a class referencing one of its interfaces. 2564inline bool CallbackInvoker::report_interface_reference(oop referrer, oop referree) { 2565 if (is_basic_heap_walk()) { 2566 return invoke_basic_object_reference_callback(JVMTI_REFERENCE_INTERFACE, referrer, referree, -1); 2567 } else { 2568 return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_INTERFACE, referrer, referree, -1); 2569 } 2570} 2571 2572// report a class referencing one of its static fields. 2573inline bool CallbackInvoker::report_static_field_reference(oop referrer, oop referree, jint slot) { 2574 if (is_basic_heap_walk()) { 2575 return invoke_basic_object_reference_callback(JVMTI_REFERENCE_STATIC_FIELD, referrer, referree, slot); 2576 } else { 2577 return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_STATIC_FIELD, referrer, referree, slot); 2578 } 2579} 2580 2581// report an array referencing an element object 2582inline bool CallbackInvoker::report_array_element_reference(oop referrer, oop referree, jint index) { 2583 if (is_basic_heap_walk()) { 2584 return invoke_basic_object_reference_callback(JVMTI_REFERENCE_ARRAY_ELEMENT, referrer, referree, index); 2585 } else { 2586 return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT, referrer, referree, index); 2587 } 2588} 2589 2590// report an object referencing an instance field object 2591inline bool CallbackInvoker::report_field_reference(oop referrer, oop referree, jint slot) { 2592 if (is_basic_heap_walk()) { 2593 return invoke_basic_object_reference_callback(JVMTI_REFERENCE_FIELD, referrer, referree, slot); 2594 } else { 2595 return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_FIELD, referrer, referree, slot); 2596 } 2597} 2598 2599// report an array referencing an element object 2600inline bool CallbackInvoker::report_constant_pool_reference(oop referrer, oop referree, jint index) { 2601 if (is_basic_heap_walk()) { 2602 return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CONSTANT_POOL, referrer, referree, index); 2603 } else { 2604 return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_CONSTANT_POOL, referrer, referree, index); 2605 } 2606} 2607 2608// A supporting closure used to process simple roots 2609class SimpleRootsClosure : public OopClosure { 2610 private: 2611 jvmtiHeapReferenceKind _kind; 2612 bool _continue; 2613 2614 jvmtiHeapReferenceKind root_kind() { return _kind; } 2615 2616 public: 2617 void set_kind(jvmtiHeapReferenceKind kind) { 2618 _kind = kind; 2619 _continue = true; 2620 } 2621 2622 inline bool stopped() { 2623 return !_continue; 2624 } 2625 2626 void do_oop(oop* obj_p) { 2627 // iteration has terminated 2628 if (stopped()) { 2629 return; 2630 } 2631 2632 // ignore null or deleted handles 2633 oop o = *obj_p; 2634 if (o == NULL || o == JNIHandles::deleted_handle()) { 2635 return; 2636 } 2637 2638 jvmtiHeapReferenceKind kind = root_kind(); 2639 2640 // many roots are Klasses so we use the java mirror 2641 if (o->is_klass()) { 2642 klassOop k = (klassOop)o; 2643 o = Klass::cast(k)->java_mirror(); 2644 } else { 2645 2646 // SystemDictionary::always_strong_oops_do reports the application 2647 // class loader as a root. We want this root to be reported as 2648 // a root kind of "OTHER" rather than "SYSTEM_CLASS". 2649 if (o->is_instance() && root_kind() == JVMTI_HEAP_REFERENCE_SYSTEM_CLASS) { 2650 kind = JVMTI_HEAP_REFERENCE_OTHER; 2651 } 2652 } 2653 2654 // some objects are ignored - in the case of simple 2655 // roots it's mostly symbolOops that we are skipping 2656 // here. 2657 if (!ServiceUtil::visible_oop(o)) { 2658 return; 2659 } 2660 2661 // invoke the callback 2662 _continue = CallbackInvoker::report_simple_root(kind, o); 2663 2664 } 2665 virtual void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } 2666}; 2667 2668// A supporting closure used to process JNI locals 2669class JNILocalRootsClosure : public OopClosure { 2670 private: 2671 jlong _thread_tag; 2672 jlong _tid; 2673 jint _depth; 2674 jmethodID _method; 2675 bool _continue; 2676 public: 2677 void set_context(jlong thread_tag, jlong tid, jint depth, jmethodID method) { 2678 _thread_tag = thread_tag; 2679 _tid = tid; 2680 _depth = depth; 2681 _method = method; 2682 _continue = true; 2683 } 2684 2685 inline bool stopped() { 2686 return !_continue; 2687 } 2688 2689 void do_oop(oop* obj_p) { 2690 // iteration has terminated 2691 if (stopped()) { 2692 return; 2693 } 2694 2695 // ignore null or deleted handles 2696 oop o = *obj_p; 2697 if (o == NULL || o == JNIHandles::deleted_handle()) { 2698 return; 2699 } 2700 2701 if (!ServiceUtil::visible_oop(o)) { 2702 return; 2703 } 2704 2705 // invoke the callback 2706 _continue = CallbackInvoker::report_jni_local_root(_thread_tag, _tid, _depth, _method, o); 2707 } 2708 virtual void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } 2709}; 2710 2711 2712// A VM operation to iterate over objects that are reachable from 2713// a set of roots or an initial object. 2714// 2715// For VM_HeapWalkOperation the set of roots used is :- 2716// 2717// - All JNI global references 2718// - All inflated monitors 2719// - All classes loaded by the boot class loader (or all classes 2720// in the event that class unloading is disabled) 2721// - All java threads 2722// - For each java thread then all locals and JNI local references 2723// on the thread's execution stack 2724// - All visible/explainable objects from Universes::oops_do 2725// 2726class VM_HeapWalkOperation: public VM_Operation { 2727 private: 2728 enum { 2729 initial_visit_stack_size = 4000 2730 }; 2731 2732 bool _is_advanced_heap_walk; // indicates FollowReferences 2733 JvmtiTagMap* _tag_map; 2734 Handle _initial_object; 2735 GrowableArray<oop>* _visit_stack; // the visit stack 2736 2737 bool _collecting_heap_roots; // are we collecting roots 2738 bool _following_object_refs; // are we following object references 2739 2740 bool _reporting_primitive_fields; // optional reporting 2741 bool _reporting_primitive_array_values; 2742 bool _reporting_string_values; 2743 2744 GrowableArray<oop>* create_visit_stack() { 2745 return new (ResourceObj::C_HEAP) GrowableArray<oop>(initial_visit_stack_size, true); 2746 } 2747 2748 // accessors 2749 bool is_advanced_heap_walk() const { return _is_advanced_heap_walk; } 2750 JvmtiTagMap* tag_map() const { return _tag_map; } 2751 Handle initial_object() const { return _initial_object; } 2752 2753 bool is_following_references() const { return _following_object_refs; } 2754 2755 bool is_reporting_primitive_fields() const { return _reporting_primitive_fields; } 2756 bool is_reporting_primitive_array_values() const { return _reporting_primitive_array_values; } 2757 bool is_reporting_string_values() const { return _reporting_string_values; } 2758 2759 GrowableArray<oop>* visit_stack() const { return _visit_stack; } 2760 2761 // iterate over the various object types 2762 inline bool iterate_over_array(oop o); 2763 inline bool iterate_over_type_array(oop o); 2764 inline bool iterate_over_class(klassOop o); 2765 inline bool iterate_over_object(oop o); 2766 2767 // root collection 2768 inline bool collect_simple_roots(); 2769 inline bool collect_stack_roots(); 2770 inline bool collect_stack_roots(JavaThread* java_thread, JNILocalRootsClosure* blk); 2771 2772 // visit an object 2773 inline bool visit(oop o); 2774 2775 public: 2776 VM_HeapWalkOperation(JvmtiTagMap* tag_map, 2777 Handle initial_object, 2778 BasicHeapWalkContext callbacks, 2779 const void* user_data); 2780 2781 VM_HeapWalkOperation(JvmtiTagMap* tag_map, 2782 Handle initial_object, 2783 AdvancedHeapWalkContext callbacks, 2784 const void* user_data); 2785 2786 ~VM_HeapWalkOperation(); 2787 2788 VMOp_Type type() const { return VMOp_HeapWalkOperation; } 2789 void doit(); 2790}; 2791 2792 2793VM_HeapWalkOperation::VM_HeapWalkOperation(JvmtiTagMap* tag_map, 2794 Handle initial_object, 2795 BasicHeapWalkContext callbacks, 2796 const void* user_data) { 2797 _is_advanced_heap_walk = false; 2798 _tag_map = tag_map; 2799 _initial_object = initial_object; 2800 _following_object_refs = (callbacks.object_ref_callback() != NULL); 2801 _reporting_primitive_fields = false; 2802 _reporting_primitive_array_values = false; 2803 _reporting_string_values = false; 2804 _visit_stack = create_visit_stack(); 2805 2806 2807 CallbackInvoker::initialize_for_basic_heap_walk(tag_map, _visit_stack, user_data, callbacks); 2808} 2809 2810VM_HeapWalkOperation::VM_HeapWalkOperation(JvmtiTagMap* tag_map, 2811 Handle initial_object, 2812 AdvancedHeapWalkContext callbacks, 2813 const void* user_data) { 2814 _is_advanced_heap_walk = true; 2815 _tag_map = tag_map; 2816 _initial_object = initial_object; 2817 _following_object_refs = true; 2818 _reporting_primitive_fields = (callbacks.primitive_field_callback() != NULL);; 2819 _reporting_primitive_array_values = (callbacks.array_primitive_value_callback() != NULL);; 2820 _reporting_string_values = (callbacks.string_primitive_value_callback() != NULL);; 2821 _visit_stack = create_visit_stack(); 2822 2823 CallbackInvoker::initialize_for_advanced_heap_walk(tag_map, _visit_stack, user_data, callbacks); 2824} 2825 2826VM_HeapWalkOperation::~VM_HeapWalkOperation() { 2827 if (_following_object_refs) { 2828 assert(_visit_stack != NULL, "checking"); 2829 delete _visit_stack; 2830 _visit_stack = NULL; 2831 } 2832} 2833 2834// an array references its class and has a reference to 2835// each element in the array 2836inline bool VM_HeapWalkOperation::iterate_over_array(oop o) { 2837 objArrayOop array = objArrayOop(o); 2838 if (array->klass() == Universe::systemObjArrayKlassObj()) { 2839 // filtered out 2840 return true; 2841 } 2842 2843 // array reference to its class 2844 oop mirror = objArrayKlass::cast(array->klass())->java_mirror(); 2845 if (!CallbackInvoker::report_class_reference(o, mirror)) { 2846 return false; 2847 } 2848 2849 // iterate over the array and report each reference to a 2850 // non-null element 2851 for (int index=0; index<array->length(); index++) { 2852 oop elem = array->obj_at(index); 2853 if (elem == NULL) { 2854 continue; 2855 } 2856 2857 // report the array reference o[index] = elem 2858 if (!CallbackInvoker::report_array_element_reference(o, elem, index)) { 2859 return false; 2860 } 2861 } 2862 return true; 2863} 2864 2865// a type array references its class 2866inline bool VM_HeapWalkOperation::iterate_over_type_array(oop o) { 2867 klassOop k = o->klass(); 2868 oop mirror = Klass::cast(k)->java_mirror(); 2869 if (!CallbackInvoker::report_class_reference(o, mirror)) { 2870 return false; 2871 } 2872 2873 // report the array contents if required 2874 if (is_reporting_primitive_array_values()) { 2875 if (!CallbackInvoker::report_primitive_array_values(o)) { 2876 return false; 2877 } 2878 } 2879 return true; 2880} 2881 2882// verify that a static oop field is in range 2883static inline bool verify_static_oop(instanceKlass* ik, 2884 klassOop k, int offset) { 2885 address obj_p = (address)k + offset; 2886 address start = (address)ik->start_of_static_fields(); 2887 address end = start + (ik->static_oop_field_size() * heapOopSize); 2888 assert(end >= start, "sanity check"); 2889 2890 if (obj_p >= start && obj_p < end) { 2891 return true; 2892 } else { 2893 return false; 2894 } 2895} 2896 2897// a class references its super class, interfaces, class loader, ... 2898// and finally its static fields 2899inline bool VM_HeapWalkOperation::iterate_over_class(klassOop k) { 2900 int i; 2901 Klass* klass = klassOop(k)->klass_part(); 2902 2903 if (klass->oop_is_instance()) { 2904 instanceKlass* ik = instanceKlass::cast(k); 2905 2906 // ignore the class if it's has been initialized yet 2907 if (!ik->is_linked()) { 2908 return true; 2909 } 2910 2911 // get the java mirror 2912 oop mirror = klass->java_mirror(); 2913 2914 // super (only if something more interesting than java.lang.Object) 2915 klassOop java_super = ik->java_super(); 2916 if (java_super != NULL && java_super != SystemDictionary::object_klass()) { 2917 oop super = Klass::cast(java_super)->java_mirror(); 2918 if (!CallbackInvoker::report_superclass_reference(mirror, super)) { 2919 return false; 2920 } 2921 } 2922 2923 // class loader 2924 oop cl = ik->class_loader(); 2925 if (cl != NULL) { 2926 if (!CallbackInvoker::report_class_loader_reference(mirror, cl)) { 2927 return false; 2928 } 2929 } 2930 2931 // protection domain 2932 oop pd = ik->protection_domain(); 2933 if (pd != NULL) { 2934 if (!CallbackInvoker::report_protection_domain_reference(mirror, pd)) { 2935 return false; 2936 } 2937 } 2938 2939 // signers 2940 oop signers = ik->signers(); 2941 if (signers != NULL) { 2942 if (!CallbackInvoker::report_signers_reference(mirror, signers)) { 2943 return false; 2944 } 2945 } 2946 2947 // references from the constant pool 2948 { 2949 const constantPoolOop pool = ik->constants(); 2950 for (int i = 1; i < pool->length(); i++) { 2951 constantTag tag = pool->tag_at(i).value(); 2952 if (tag.is_string() || tag.is_klass()) { 2953 oop entry; 2954 if (tag.is_string()) { 2955 entry = pool->resolved_string_at(i); 2956 assert(java_lang_String::is_instance(entry), "must be string"); 2957 } else { 2958 entry = Klass::cast(pool->resolved_klass_at(i))->java_mirror(); 2959 } 2960 if (!CallbackInvoker::report_constant_pool_reference(mirror, entry, (jint)i)) { 2961 return false; 2962 } 2963 } 2964 } 2965 } 2966 2967 // interfaces 2968 // (These will already have been reported as references from the constant pool 2969 // but are specified by IterateOverReachableObjects and must be reported). 2970 objArrayOop interfaces = ik->local_interfaces(); 2971 for (i = 0; i < interfaces->length(); i++) { 2972 oop interf = Klass::cast((klassOop)interfaces->obj_at(i))->java_mirror(); 2973 if (interf == NULL) { 2974 continue; 2975 } 2976 if (!CallbackInvoker::report_interface_reference(mirror, interf)) { 2977 return false; 2978 } 2979 } 2980 2981 // iterate over the static fields 2982 2983 ClassFieldMap* field_map = ClassFieldMap::create_map_of_static_fields(k); 2984 for (i=0; i<field_map->field_count(); i++) { 2985 ClassFieldDescriptor* field = field_map->field_at(i); 2986 char type = field->field_type(); 2987 if (!is_primitive_field_type(type)) { 2988 oop fld_o = k->obj_field(field->field_offset()); 2989 assert(verify_static_oop(ik, k, field->field_offset()), "sanity check"); 2990 if (fld_o != NULL) { 2991 int slot = field->field_index(); 2992 if (!CallbackInvoker::report_static_field_reference(mirror, fld_o, slot)) { 2993 delete field_map; 2994 return false; 2995 } 2996 } 2997 } else { 2998 if (is_reporting_primitive_fields()) { 2999 address addr = (address)k + field->field_offset(); 3000 int slot = field->field_index(); 3001 if (!CallbackInvoker::report_primitive_static_field(mirror, slot, addr, type)) { 3002 delete field_map; 3003 return false; 3004 } 3005 } 3006 } 3007 } 3008 delete field_map; 3009 3010 return true; 3011 } 3012 3013 return true; 3014} 3015 3016// an object references a class and its instance fields 3017// (static fields are ignored here as we report these as 3018// references from the class). 3019inline bool VM_HeapWalkOperation::iterate_over_object(oop o) { 3020 // reference to the class 3021 if (!CallbackInvoker::report_class_reference(o, Klass::cast(o->klass())->java_mirror())) { 3022 return false; 3023 } 3024 3025 // iterate over instance fields 3026 ClassFieldMap* field_map = JvmtiCachedClassFieldMap::get_map_of_instance_fields(o); 3027 for (int i=0; i<field_map->field_count(); i++) { 3028 ClassFieldDescriptor* field = field_map->field_at(i); 3029 char type = field->field_type(); 3030 if (!is_primitive_field_type(type)) { 3031 oop fld_o = o->obj_field(field->field_offset()); 3032 if (fld_o != NULL) { 3033 // reflection code may have a reference to a klassOop. 3034 // - see sun.reflect.UnsafeStaticFieldAccessorImpl and sun.misc.Unsafe 3035 if (fld_o->is_klass()) { 3036 klassOop k = (klassOop)fld_o; 3037 fld_o = Klass::cast(k)->java_mirror(); 3038 } 3039 int slot = field->field_index(); 3040 if (!CallbackInvoker::report_field_reference(o, fld_o, slot)) { 3041 return false; 3042 } 3043 } 3044 } else { 3045 if (is_reporting_primitive_fields()) { 3046 // primitive instance field 3047 address addr = (address)o + field->field_offset(); 3048 int slot = field->field_index(); 3049 if (!CallbackInvoker::report_primitive_instance_field(o, slot, addr, type)) { 3050 return false; 3051 } 3052 } 3053 } 3054 } 3055 3056 // if the object is a java.lang.String 3057 if (is_reporting_string_values() && 3058 o->klass() == SystemDictionary::string_klass()) { 3059 if (!CallbackInvoker::report_string_value(o)) { 3060 return false; 3061 } 3062 } 3063 return true; 3064} 3065 3066 3067// collects all simple (non-stack) roots. 3068// if there's a heap root callback provided then the callback is 3069// invoked for each simple root. 3070// if an object reference callback is provided then all simple 3071// roots are pushed onto the marking stack so that they can be 3072// processed later 3073// 3074inline bool VM_HeapWalkOperation::collect_simple_roots() { 3075 SimpleRootsClosure blk; 3076 3077 // JNI globals 3078 blk.set_kind(JVMTI_HEAP_REFERENCE_JNI_GLOBAL); 3079 JNIHandles::oops_do(&blk); 3080 if (blk.stopped()) { 3081 return false; 3082 } 3083 3084 // Preloaded classes and loader from the system dictionary 3085 blk.set_kind(JVMTI_HEAP_REFERENCE_SYSTEM_CLASS); 3086 SystemDictionary::always_strong_oops_do(&blk); 3087 if (blk.stopped()) { 3088 return false; 3089 } 3090 3091 // Inflated monitors 3092 blk.set_kind(JVMTI_HEAP_REFERENCE_MONITOR); 3093 ObjectSynchronizer::oops_do(&blk); 3094 if (blk.stopped()) { 3095 return false; 3096 } 3097 3098 // Threads 3099 for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) { 3100 oop threadObj = thread->threadObj(); 3101 if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) { 3102 bool cont = CallbackInvoker::report_simple_root(JVMTI_HEAP_REFERENCE_THREAD, threadObj); 3103 if (!cont) { 3104 return false; 3105 } 3106 } 3107 } 3108 3109 // Other kinds of roots maintained by HotSpot 3110 // Many of these won't be visible but others (such as instances of important 3111 // exceptions) will be visible. 3112 blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER); 3113 Universe::oops_do(&blk); 3114 return true; 3115} 3116 3117// Walk the stack of a given thread and find all references (locals 3118// and JNI calls) and report these as stack references 3119inline bool VM_HeapWalkOperation::collect_stack_roots(JavaThread* java_thread, 3120 JNILocalRootsClosure* blk) 3121{ 3122 oop threadObj = java_thread->threadObj(); 3123 assert(threadObj != NULL, "sanity check"); 3124 3125 // only need to get the thread's tag once per thread 3126 jlong thread_tag = tag_for(_tag_map, threadObj); 3127 3128 // also need the thread id 3129 jlong tid = java_lang_Thread::thread_id(threadObj); 3130 3131 3132 if (java_thread->has_last_Java_frame()) { 3133 3134 // vframes are resource allocated 3135 Thread* current_thread = Thread::current(); 3136 ResourceMark rm(current_thread); 3137 HandleMark hm(current_thread); 3138 3139 RegisterMap reg_map(java_thread); 3140 frame f = java_thread->last_frame(); 3141 vframe* vf = vframe::new_vframe(&f, ®_map, java_thread); 3142 3143 bool is_top_frame = true; 3144 int depth = 0; 3145 frame* last_entry_frame = NULL; 3146 3147 while (vf != NULL) { 3148 if (vf->is_java_frame()) { 3149 3150 // java frame (interpreted, compiled, ...) 3151 javaVFrame *jvf = javaVFrame::cast(vf); 3152 3153 // the jmethodID 3154 jmethodID method = jvf->method()->jmethod_id(); 3155 3156 if (!(jvf->method()->is_native())) { 3157 jlocation bci = (jlocation)jvf->bci(); 3158 StackValueCollection* locals = jvf->locals(); 3159 for (int slot=0; slot<locals->size(); slot++) { 3160 if (locals->at(slot)->type() == T_OBJECT) { 3161 oop o = locals->obj_at(slot)(); 3162 if (o == NULL) { 3163 continue; 3164 } 3165 3166 // stack reference 3167 if (!CallbackInvoker::report_stack_ref_root(thread_tag, tid, depth, method, 3168 bci, slot, o)) { 3169 return false; 3170 } 3171 } 3172 } 3173 } else { 3174 blk->set_context(thread_tag, tid, depth, method); 3175 if (is_top_frame) { 3176 // JNI locals for the top frame. 3177 java_thread->active_handles()->oops_do(blk); 3178 } else { 3179 if (last_entry_frame != NULL) { 3180 // JNI locals for the entry frame 3181 assert(last_entry_frame->is_entry_frame(), "checking"); 3182 last_entry_frame->entry_frame_call_wrapper()->handles()->oops_do(blk); 3183 } 3184 } 3185 } 3186 last_entry_frame = NULL; 3187 depth++; 3188 } else { 3189 // externalVFrame - for an entry frame then we report the JNI locals 3190 // when we find the corresponding javaVFrame 3191 frame* fr = vf->frame_pointer(); 3192 assert(fr != NULL, "sanity check"); 3193 if (fr->is_entry_frame()) { 3194 last_entry_frame = fr; 3195 } 3196 } 3197 3198 vf = vf->sender(); 3199 is_top_frame = false; 3200 } 3201 } else { 3202 // no last java frame but there may be JNI locals 3203 blk->set_context(thread_tag, tid, 0, (jmethodID)NULL); 3204 java_thread->active_handles()->oops_do(blk); 3205 } 3206 return true; 3207} 3208 3209 3210// collects all stack roots - for each thread it walks the execution 3211// stack to find all references and local JNI refs. 3212inline bool VM_HeapWalkOperation::collect_stack_roots() { 3213 JNILocalRootsClosure blk; 3214 for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) { 3215 oop threadObj = thread->threadObj(); 3216 if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) { 3217 if (!collect_stack_roots(thread, &blk)) { 3218 return false; 3219 } 3220 } 3221 } 3222 return true; 3223} 3224 3225// visit an object 3226// first mark the object as visited 3227// second get all the outbound references from this object (in other words, all 3228// the objects referenced by this object). 3229// 3230bool VM_HeapWalkOperation::visit(oop o) { 3231 // mark object as visited 3232 assert(!ObjectMarker::visited(o), "can't visit same object more than once"); 3233 ObjectMarker::mark(o); 3234 3235 // instance 3236 if (o->is_instance()) { 3237 if (o->klass() == SystemDictionary::class_klass()) { 3238 o = klassOop_if_java_lang_Class(o); 3239 if (o->is_klass()) { 3240 // a java.lang.Class 3241 return iterate_over_class(klassOop(o)); 3242 } 3243 } else { 3244 return iterate_over_object(o); 3245 } 3246 } 3247 3248 // object array 3249 if (o->is_objArray()) { 3250 return iterate_over_array(o); 3251 } 3252 3253 // type array 3254 if (o->is_typeArray()) { 3255 return iterate_over_type_array(o); 3256 } 3257 3258 return true; 3259} 3260 3261void VM_HeapWalkOperation::doit() { 3262 ResourceMark rm; 3263 ObjectMarkerController marker; 3264 ClassFieldMapCacheMark cm; 3265 3266 assert(visit_stack()->is_empty(), "visit stack must be empty"); 3267 3268 // the heap walk starts with an initial object or the heap roots 3269 if (initial_object().is_null()) { 3270 if (!collect_simple_roots()) return; 3271 if (!collect_stack_roots()) return; 3272 } else { 3273 visit_stack()->push(initial_object()()); 3274 } 3275 3276 // object references required 3277 if (is_following_references()) { 3278 3279 // visit each object until all reachable objects have been 3280 // visited or the callback asked to terminate the iteration. 3281 while (!visit_stack()->is_empty()) { 3282 oop o = visit_stack()->pop(); 3283 if (!ObjectMarker::visited(o)) { 3284 if (!visit(o)) { 3285 break; 3286 } 3287 } 3288 } 3289 } 3290} 3291 3292// iterate over all objects that are reachable from a set of roots 3293void JvmtiTagMap::iterate_over_reachable_objects(jvmtiHeapRootCallback heap_root_callback, 3294 jvmtiStackReferenceCallback stack_ref_callback, 3295 jvmtiObjectReferenceCallback object_ref_callback, 3296 const void* user_data) { 3297 MutexLocker ml(Heap_lock); 3298 BasicHeapWalkContext context(heap_root_callback, stack_ref_callback, object_ref_callback); 3299 VM_HeapWalkOperation op(this, Handle(), context, user_data); 3300 VMThread::execute(&op); 3301} 3302 3303// iterate over all objects that are reachable from a given object 3304void JvmtiTagMap::iterate_over_objects_reachable_from_object(jobject object, 3305 jvmtiObjectReferenceCallback object_ref_callback, 3306 const void* user_data) { 3307 oop obj = JNIHandles::resolve(object); 3308 Handle initial_object(Thread::current(), obj); 3309 3310 MutexLocker ml(Heap_lock); 3311 BasicHeapWalkContext context(NULL, NULL, object_ref_callback); 3312 VM_HeapWalkOperation op(this, initial_object, context, user_data); 3313 VMThread::execute(&op); 3314} 3315 3316// follow references from an initial object or the GC roots 3317void JvmtiTagMap::follow_references(jint heap_filter, 3318 KlassHandle klass, 3319 jobject object, 3320 const jvmtiHeapCallbacks* callbacks, 3321 const void* user_data) 3322{ 3323 oop obj = JNIHandles::resolve(object); 3324 Handle initial_object(Thread::current(), obj); 3325 3326 MutexLocker ml(Heap_lock); 3327 AdvancedHeapWalkContext context(heap_filter, klass, callbacks); 3328 VM_HeapWalkOperation op(this, initial_object, context, user_data); 3329 VMThread::execute(&op); 3330} 3331 3332 3333// called post-GC 3334// - for each JVMTI environment with an object tag map, call its rehash 3335// function to re-sync with the new object locations. 3336void JvmtiTagMap::gc_epilogue(bool full) { 3337 assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint"); 3338 if (JvmtiEnv::environments_might_exist()) { 3339 // re-obtain the memory region for the young generation (might 3340 // changed due to adaptive resizing policy) 3341 get_young_generation(); 3342 3343 JvmtiEnvIterator it; 3344 for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) { 3345 JvmtiTagMap* tag_map = env->tag_map(); 3346 if (tag_map != NULL && !tag_map->is_empty()) { 3347 TraceTime t(full ? "JVMTI Full Rehash " : "JVMTI Rehash ", TraceJVMTIObjectTagging); 3348 if (full) { 3349 tag_map->rehash(0, n_hashmaps); 3350 } else { 3351 tag_map->rehash(0, 0); // tag map for young gen only 3352 } 3353 } 3354 } 3355 } 3356} 3357 3358// CMS has completed referencing processing so we may have JNI weak refs 3359// to objects in the CMS generation that have been GC'ed. 3360void JvmtiTagMap::cms_ref_processing_epilogue() { 3361 assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint"); 3362 assert(UseConcMarkSweepGC, "should only be used with CMS"); 3363 if (JvmtiEnv::environments_might_exist()) { 3364 JvmtiEnvIterator it; 3365 for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) { 3366 JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map(); 3367 if (tag_map != NULL && !tag_map->is_empty()) { 3368 TraceTime t("JVMTI Rehash (CMS) ", TraceJVMTIObjectTagging); 3369 tag_map->rehash(1, n_hashmaps); // assume CMS not used in young gen 3370 } 3371 } 3372 } 3373} 3374 3375 3376// For each entry in the hashmaps 'start' to 'end' : 3377// 3378// 1. resolve the JNI weak reference 3379// 3380// 2. If it resolves to NULL it means the object has been freed so the entry 3381// is removed, the weak reference destroyed, and the object free event is 3382// posted (if enabled). 3383// 3384// 3. If the weak reference resolves to an object then we re-hash the object 3385// to see if it has moved or has been promoted (from the young to the old 3386// generation for example). 3387// 3388void JvmtiTagMap::rehash(int start, int end) { 3389 3390 // does this environment have the OBJECT_FREE event enabled 3391 bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE); 3392 3393 // counters used for trace message 3394 int freed = 0; 3395 int moved = 0; 3396 int promoted = 0; 3397 3398 // we assume there are two hashmaps - one for the young generation 3399 // and the other for all other spaces. 3400 assert(n_hashmaps == 2, "not implemented"); 3401 JvmtiTagHashmap* young_hashmap = _hashmap[0]; 3402 JvmtiTagHashmap* other_hashmap = _hashmap[1]; 3403 3404 // reenable sizing (if disabled) 3405 young_hashmap->set_resizing_enabled(true); 3406 other_hashmap->set_resizing_enabled(true); 3407 3408 // when re-hashing the hashmap corresponding to the young generation we 3409 // collect the entries corresponding to objects that have been promoted. 3410 JvmtiTagHashmapEntry* promoted_entries = NULL; 3411 3412 if (end >= n_hashmaps) { 3413 end = n_hashmaps - 1; 3414 } 3415 3416 for (int i=start; i <= end; i++) { 3417 JvmtiTagHashmap* hashmap = _hashmap[i]; 3418 3419 // if the hashmap is empty then we can skip it 3420 if (hashmap->_entry_count == 0) { 3421 continue; 3422 } 3423 3424 // now iterate through each entry in the table 3425 3426 JvmtiTagHashmapEntry** table = hashmap->table(); 3427 int size = hashmap->size(); 3428 3429 for (int pos=0; pos<size; pos++) { 3430 JvmtiTagHashmapEntry* entry = table[pos]; 3431 JvmtiTagHashmapEntry* prev = NULL; 3432 3433 while (entry != NULL) { 3434 JvmtiTagHashmapEntry* next = entry->next(); 3435 3436 jweak ref = entry->object(); 3437 oop oop = JNIHandles::resolve(ref); 3438 3439 // has object been GC'ed 3440 if (oop == NULL) { 3441 // grab the tag 3442 jlong tag = entry->tag(); 3443 guarantee(tag != 0, "checking"); 3444 3445 // remove GC'ed entry from hashmap and return the 3446 // entry to the free list 3447 hashmap->remove(prev, pos, entry); 3448 destroy_entry(entry); 3449 3450 // destroy the weak ref 3451 JNIHandles::destroy_weak_global(ref); 3452 3453 // post the event to the profiler 3454 if (post_object_free) { 3455 JvmtiExport::post_object_free(env(), tag); 3456 } 3457 3458 freed++; 3459 entry = next; 3460 continue; 3461 } 3462 3463 // if this is the young hashmap then the object is either promoted 3464 // or moved. 3465 // if this is the other hashmap then the object is moved. 3466 3467 bool same_gen; 3468 if (i == 0) { 3469 assert(hashmap == young_hashmap, "checking"); 3470 same_gen = is_in_young(oop); 3471 } else { 3472 same_gen = true; 3473 } 3474 3475 3476 if (same_gen) { 3477 // if the object has moved then re-hash it and move its 3478 // entry to its new location. 3479 unsigned int new_pos = JvmtiTagHashmap::hash(oop, size); 3480 if (new_pos != (unsigned int)pos) { 3481 if (prev == NULL) { 3482 table[pos] = next; 3483 } else { 3484 prev->set_next(next); 3485 } 3486 entry->set_next(table[new_pos]); 3487 table[new_pos] = entry; 3488 moved++; 3489 } else { 3490 // object didn't move 3491 prev = entry; 3492 } 3493 } else { 3494 // object has been promoted so remove the entry from the 3495 // young hashmap 3496 assert(hashmap == young_hashmap, "checking"); 3497 hashmap->remove(prev, pos, entry); 3498 3499 // move the entry to the promoted list 3500 entry->set_next(promoted_entries); 3501 promoted_entries = entry; 3502 } 3503 3504 entry = next; 3505 } 3506 } 3507 } 3508 3509 3510 // add the entries, corresponding to the promoted objects, to the 3511 // other hashmap. 3512 JvmtiTagHashmapEntry* entry = promoted_entries; 3513 while (entry != NULL) { 3514 oop o = JNIHandles::resolve(entry->object()); 3515 assert(hashmap_for(o) == other_hashmap, "checking"); 3516 JvmtiTagHashmapEntry* next = entry->next(); 3517 other_hashmap->add(o, entry); 3518 entry = next; 3519 promoted++; 3520 } 3521 3522 // stats 3523 if (TraceJVMTIObjectTagging) { 3524 int total_moves = promoted + moved; 3525 3526 int post_total = 0; 3527 for (int i=0; i<n_hashmaps; i++) { 3528 post_total += _hashmap[i]->_entry_count; 3529 } 3530 int pre_total = post_total + freed; 3531 3532 tty->print("(%d->%d, %d freed, %d promoted, %d total moves)", 3533 pre_total, post_total, freed, promoted, total_moves); 3534 } 3535} 3536