8276696: ParallelObjectIterator freed at the wrong time in VM_HeapDumper
Reviewed-by: pliden, stefank
This commit is contained in:
parent
90f96fb4db
commit
f4dc03ea6d
src/hotspot/share
gc
g1
parallel
shared
shenandoah
z
memory
services
@ -2260,7 +2260,7 @@ void G1CollectedHeap::object_iterate(ObjectClosure* cl) {
|
|||||||
heap_region_iterate(&blk);
|
heap_region_iterate(&blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
class G1ParallelObjectIterator : public ParallelObjectIterator {
|
class G1ParallelObjectIterator : public ParallelObjectIteratorImpl {
|
||||||
private:
|
private:
|
||||||
G1CollectedHeap* _heap;
|
G1CollectedHeap* _heap;
|
||||||
HeapRegionClaimer _claimer;
|
HeapRegionClaimer _claimer;
|
||||||
@ -2275,7 +2275,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ParallelObjectIterator* G1CollectedHeap::parallel_object_iterator(uint thread_num) {
|
ParallelObjectIteratorImpl* G1CollectedHeap::parallel_object_iterator(uint thread_num) {
|
||||||
return new G1ParallelObjectIterator(thread_num);
|
return new G1ParallelObjectIterator(thread_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,7 +1077,7 @@ public:
|
|||||||
// Iterate over all objects, calling "cl.do_object" on each.
|
// Iterate over all objects, calling "cl.do_object" on each.
|
||||||
void object_iterate(ObjectClosure* cl) override;
|
void object_iterate(ObjectClosure* cl) override;
|
||||||
|
|
||||||
ParallelObjectIterator* parallel_object_iterator(uint thread_num) override;
|
ParallelObjectIteratorImpl* parallel_object_iterator(uint thread_num) override;
|
||||||
|
|
||||||
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
|
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
|
||||||
void keep_alive(oop obj) override;
|
void keep_alive(oop obj) override;
|
||||||
|
@ -600,7 +600,7 @@ void ParallelScavengeHeap::object_iterate_parallel(ObjectClosure* cl,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PSScavengeParallelObjectIterator : public ParallelObjectIterator {
|
class PSScavengeParallelObjectIterator : public ParallelObjectIteratorImpl {
|
||||||
private:
|
private:
|
||||||
ParallelScavengeHeap* _heap;
|
ParallelScavengeHeap* _heap;
|
||||||
HeapBlockClaimer _claimer;
|
HeapBlockClaimer _claimer;
|
||||||
@ -615,7 +615,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ParallelObjectIterator* ParallelScavengeHeap::parallel_object_iterator(uint thread_num) {
|
ParallelObjectIteratorImpl* ParallelScavengeHeap::parallel_object_iterator(uint thread_num) {
|
||||||
return new PSScavengeParallelObjectIterator();
|
return new PSScavengeParallelObjectIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ class ParallelScavengeHeap : public CollectedHeap {
|
|||||||
|
|
||||||
void object_iterate(ObjectClosure* cl);
|
void object_iterate(ObjectClosure* cl);
|
||||||
void object_iterate_parallel(ObjectClosure* cl, HeapBlockClaimer* claimer);
|
void object_iterate_parallel(ObjectClosure* cl, HeapBlockClaimer* claimer);
|
||||||
virtual ParallelObjectIterator* parallel_object_iterator(uint thread_num);
|
virtual ParallelObjectIteratorImpl* parallel_object_iterator(uint thread_num);
|
||||||
|
|
||||||
HeapWord* block_start(const void* addr) const;
|
HeapWord* block_start(const void* addr) const;
|
||||||
bool block_is_obj(const HeapWord* addr) const;
|
bool block_is_obj(const HeapWord* addr) const;
|
||||||
|
@ -110,6 +110,18 @@ void GCHeapLog::log_heap(CollectedHeap* heap, bool before) {
|
|||||||
st.print_cr("}");
|
st.print_cr("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParallelObjectIterator::ParallelObjectIterator(uint thread_num) :
|
||||||
|
_impl(Universe::heap()->parallel_object_iterator(thread_num))
|
||||||
|
{}
|
||||||
|
|
||||||
|
ParallelObjectIterator::~ParallelObjectIterator() {
|
||||||
|
delete _impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParallelObjectIterator::object_iterate(ObjectClosure* cl, uint worker_id) {
|
||||||
|
_impl->object_iterate(cl, worker_id);
|
||||||
|
}
|
||||||
|
|
||||||
size_t CollectedHeap::unused() const {
|
size_t CollectedHeap::unused() const {
|
||||||
MutexLocker ml(Heap_lock);
|
MutexLocker ml(Heap_lock);
|
||||||
return capacity() - used();
|
return capacity() - used();
|
||||||
|
@ -62,10 +62,23 @@ class VirtualSpaceSummary;
|
|||||||
class WorkerThreads;
|
class WorkerThreads;
|
||||||
class nmethod;
|
class nmethod;
|
||||||
|
|
||||||
class ParallelObjectIterator : public CHeapObj<mtGC> {
|
class ParallelObjectIteratorImpl : public CHeapObj<mtGC> {
|
||||||
public:
|
public:
|
||||||
|
virtual ~ParallelObjectIteratorImpl() {}
|
||||||
virtual void object_iterate(ObjectClosure* cl, uint worker_id) = 0;
|
virtual void object_iterate(ObjectClosure* cl, uint worker_id) = 0;
|
||||||
virtual ~ParallelObjectIterator() {}
|
};
|
||||||
|
|
||||||
|
// User facing parallel object iterator. This is a StackObj, which ensures that
|
||||||
|
// the _impl is allocated and deleted in the scope of this object. This ensures
|
||||||
|
// the life cycle of the implementation is as required by ThreadsListHandle,
|
||||||
|
// which is sometimes used by the root iterators.
|
||||||
|
class ParallelObjectIterator : public StackObj {
|
||||||
|
ParallelObjectIteratorImpl* _impl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ParallelObjectIterator(uint thread_num);
|
||||||
|
~ParallelObjectIterator();
|
||||||
|
void object_iterate(ObjectClosure* cl, uint worker_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -82,6 +95,7 @@ class CollectedHeap : public CHeapObj<mtInternal> {
|
|||||||
friend class JVMCIVMStructs;
|
friend class JVMCIVMStructs;
|
||||||
friend class IsGCActiveMark; // Block structured external access to _is_gc_active
|
friend class IsGCActiveMark; // Block structured external access to _is_gc_active
|
||||||
friend class MemAllocator;
|
friend class MemAllocator;
|
||||||
|
friend class ParallelObjectIterator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GCHeapLog* _gc_heap_log;
|
GCHeapLog* _gc_heap_log;
|
||||||
@ -384,10 +398,12 @@ class CollectedHeap : public CHeapObj<mtInternal> {
|
|||||||
// Iterate over all objects, calling "cl.do_object" on each.
|
// Iterate over all objects, calling "cl.do_object" on each.
|
||||||
virtual void object_iterate(ObjectClosure* cl) = 0;
|
virtual void object_iterate(ObjectClosure* cl) = 0;
|
||||||
|
|
||||||
virtual ParallelObjectIterator* parallel_object_iterator(uint thread_num) {
|
protected:
|
||||||
|
virtual ParallelObjectIteratorImpl* parallel_object_iterator(uint thread_num) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
|
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
|
||||||
virtual void keep_alive(oop obj) {}
|
virtual void keep_alive(oop obj) {}
|
||||||
|
|
||||||
|
@ -1366,7 +1366,7 @@ public:
|
|||||||
// parallel marking queues.
|
// parallel marking queues.
|
||||||
// Every worker processes it's own marking queue. work-stealing is used
|
// Every worker processes it's own marking queue. work-stealing is used
|
||||||
// to balance workload.
|
// to balance workload.
|
||||||
class ShenandoahParallelObjectIterator : public ParallelObjectIterator {
|
class ShenandoahParallelObjectIterator : public ParallelObjectIteratorImpl {
|
||||||
private:
|
private:
|
||||||
uint _num_workers;
|
uint _num_workers;
|
||||||
bool _init_ready;
|
bool _init_ready;
|
||||||
@ -1465,7 +1465,7 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ParallelObjectIterator* ShenandoahHeap::parallel_object_iterator(uint workers) {
|
ParallelObjectIteratorImpl* ShenandoahHeap::parallel_object_iterator(uint workers) {
|
||||||
return new ShenandoahParallelObjectIterator(workers, &_aux_bit_map);
|
return new ShenandoahParallelObjectIterator(workers, &_aux_bit_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,7 +484,7 @@ public:
|
|||||||
// Used for native heap walkers: heap dumpers, mostly
|
// Used for native heap walkers: heap dumpers, mostly
|
||||||
void object_iterate(ObjectClosure* cl);
|
void object_iterate(ObjectClosure* cl);
|
||||||
// Parallel heap iteration support
|
// Parallel heap iteration support
|
||||||
virtual ParallelObjectIterator* parallel_object_iterator(uint workers);
|
virtual ParallelObjectIteratorImpl* parallel_object_iterator(uint workers);
|
||||||
|
|
||||||
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
|
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
|
||||||
void keep_alive(oop obj);
|
void keep_alive(oop obj);
|
||||||
|
@ -226,7 +226,7 @@ void ZCollectedHeap::object_iterate(ObjectClosure* cl) {
|
|||||||
_heap.object_iterate(cl, true /* visit_weaks */);
|
_heap.object_iterate(cl, true /* visit_weaks */);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParallelObjectIterator* ZCollectedHeap::parallel_object_iterator(uint nworkers) {
|
ParallelObjectIteratorImpl* ZCollectedHeap::parallel_object_iterator(uint nworkers) {
|
||||||
return _heap.parallel_object_iterator(nworkers, true /* visit_weaks */);
|
return _heap.parallel_object_iterator(nworkers, true /* visit_weaks */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ public:
|
|||||||
virtual GrowableArray<MemoryPool*> memory_pools();
|
virtual GrowableArray<MemoryPool*> memory_pools();
|
||||||
|
|
||||||
virtual void object_iterate(ObjectClosure* cl);
|
virtual void object_iterate(ObjectClosure* cl);
|
||||||
virtual ParallelObjectIterator* parallel_object_iterator(uint nworkers);
|
virtual ParallelObjectIteratorImpl* parallel_object_iterator(uint nworkers);
|
||||||
|
|
||||||
virtual void keep_alive(oop obj);
|
virtual void keep_alive(oop obj);
|
||||||
|
|
||||||
|
@ -439,7 +439,7 @@ void ZHeap::object_iterate(ObjectClosure* cl, bool visit_weaks) {
|
|||||||
iter.object_iterate(cl, 0 /* worker_id */);
|
iter.object_iterate(cl, 0 /* worker_id */);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParallelObjectIterator* ZHeap::parallel_object_iterator(uint nworkers, bool visit_weaks) {
|
ParallelObjectIteratorImpl* ZHeap::parallel_object_iterator(uint nworkers, bool visit_weaks) {
|
||||||
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
|
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
|
||||||
return new ZHeapIterator(nworkers, visit_weaks);
|
return new ZHeapIterator(nworkers, visit_weaks);
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ public:
|
|||||||
|
|
||||||
// Iteration
|
// Iteration
|
||||||
void object_iterate(ObjectClosure* cl, bool visit_weaks);
|
void object_iterate(ObjectClosure* cl, bool visit_weaks);
|
||||||
ParallelObjectIterator* parallel_object_iterator(uint nworkers, bool visit_weaks);
|
ParallelObjectIteratorImpl* parallel_object_iterator(uint nworkers, bool visit_weaks);
|
||||||
void pages_do(ZPageClosure* cl);
|
void pages_do(ZPageClosure* cl);
|
||||||
|
|
||||||
// Serviceability
|
// Serviceability
|
||||||
|
@ -42,7 +42,7 @@ using ZHeapIteratorQueues = GenericTaskQueueSet<ZHeapIteratorQueue, mtGC>;
|
|||||||
using ZHeapIteratorArrayQueue = OverflowTaskQueue<ObjArrayTask, mtGC>;
|
using ZHeapIteratorArrayQueue = OverflowTaskQueue<ObjArrayTask, mtGC>;
|
||||||
using ZHeapIteratorArrayQueues = GenericTaskQueueSet<ZHeapIteratorArrayQueue, mtGC>;
|
using ZHeapIteratorArrayQueues = GenericTaskQueueSet<ZHeapIteratorArrayQueue, mtGC>;
|
||||||
|
|
||||||
class ZHeapIterator : public ParallelObjectIterator {
|
class ZHeapIterator : public ParallelObjectIteratorImpl {
|
||||||
friend class ZHeapIteratorContext;
|
friend class ZHeapIteratorContext;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -578,21 +578,15 @@ uintx HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *fil
|
|||||||
const uint capped_parallel_thread_num = MIN2(parallel_thread_num, workers->max_workers());
|
const uint capped_parallel_thread_num = MIN2(parallel_thread_num, workers->max_workers());
|
||||||
WithActiveWorkers with_active_workers(workers, capped_parallel_thread_num);
|
WithActiveWorkers with_active_workers(workers, capped_parallel_thread_num);
|
||||||
|
|
||||||
ParallelObjectIterator* poi = Universe::heap()->parallel_object_iterator(workers->active_workers());
|
ParallelObjectIterator poi(workers->active_workers());
|
||||||
if (poi != NULL) {
|
ParHeapInspectTask task(&poi, cit, filter);
|
||||||
// The GC supports parallel object iteration.
|
|
||||||
|
|
||||||
ParHeapInspectTask task(poi, cit, filter);
|
|
||||||
// Run task with the active workers.
|
// Run task with the active workers.
|
||||||
workers->run_task(&task);
|
workers->run_task(&task);
|
||||||
|
|
||||||
delete poi;
|
|
||||||
if (task.success()) {
|
if (task.success()) {
|
||||||
return task.missed_count();
|
return task.missed_count();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
// If no parallel iteration available, run serially.
|
// If no parallel iteration available, run serially.
|
||||||
|
@ -1910,7 +1910,6 @@ class VM_HeapDumper : public VM_GC_Operation, public WorkerTask {
|
|||||||
// Number of dumper threads that only iterate heap.
|
// Number of dumper threads that only iterate heap.
|
||||||
uint _heap_only_dumper_threads = _num_dumper_threads - 1 /* VMDumper thread */;
|
uint _heap_only_dumper_threads = _num_dumper_threads - 1 /* VMDumper thread */;
|
||||||
_dumper_controller = new (std::nothrow) DumperController(_heap_only_dumper_threads);
|
_dumper_controller = new (std::nothrow) DumperController(_heap_only_dumper_threads);
|
||||||
_poi = Universe::heap()->parallel_object_iterator(_num_dumper_threads);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1999,10 +1998,6 @@ class VM_HeapDumper : public VM_GC_Operation, public WorkerTask {
|
|||||||
}
|
}
|
||||||
FREE_C_HEAP_ARRAY(ThreadStackTrace*, _stack_traces);
|
FREE_C_HEAP_ARRAY(ThreadStackTrace*, _stack_traces);
|
||||||
}
|
}
|
||||||
if (_poi != NULL) {
|
|
||||||
delete _poi;
|
|
||||||
_poi = NULL;
|
|
||||||
}
|
|
||||||
if (_dumper_controller != NULL) {
|
if (_dumper_controller != NULL) {
|
||||||
delete _dumper_controller;
|
delete _dumper_controller;
|
||||||
_dumper_controller = NULL;
|
_dumper_controller = NULL;
|
||||||
@ -2252,7 +2247,14 @@ void VM_HeapDumper::doit() {
|
|||||||
work(0);
|
work(0);
|
||||||
} else {
|
} else {
|
||||||
prepare_parallel_dump(workers->active_workers());
|
prepare_parallel_dump(workers->active_workers());
|
||||||
|
if (_num_dumper_threads > 1) {
|
||||||
|
ParallelObjectIterator poi(_num_dumper_threads);
|
||||||
|
_poi = &poi;
|
||||||
workers->run_task(this);
|
workers->run_task(this);
|
||||||
|
_poi = NULL;
|
||||||
|
} else {
|
||||||
|
workers->run_task(this);
|
||||||
|
}
|
||||||
finish_parallel_dump();
|
finish_parallel_dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user