提交 f7d6a4e8 编写于 作者: T tonyp

6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC

Summary: It introduces the necessary memory pools for G1.
Reviewed-by: mchung, ysr
上级 bef9ec13
......@@ -928,6 +928,8 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
TraceTime t(full ? "Full GC (System.gc())" : "Full GC", PrintGC, true, gclog_or_tty);
TraceMemoryManagerStats tms(true /* fullGC */);
double start = os::elapsedTime();
g1_policy()->record_full_collection_start();
......@@ -1001,6 +1003,8 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
MemoryService::track_memory_usage();
if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
gclog_or_tty->print(" VerifyAfterGC:");
......@@ -2645,6 +2649,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint() {
}
{
ResourceMark rm;
char verbose_str[128];
sprintf(verbose_str, "GC pause ");
if (g1_policy()->in_young_gc_mode()) {
......@@ -2663,7 +2669,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint() {
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty);
ResourceMark rm;
TraceMemoryManagerStats tms(false /* fullGC */);
assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
guarantee(!is_gc_active(), "collection is not reentrant");
......@@ -2859,6 +2866,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint() {
assert(regions_accounted_for(), "Region leakage.");
MemoryService::track_memory_usage();
if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
gclog_or_tty->print(" VerifyAfterGC:");
......
......@@ -222,6 +222,15 @@ g1MarkSweep.hpp oop.hpp
g1MarkSweep.hpp timer.hpp
g1MarkSweep.hpp universe.hpp
g1MemoryPool.cpp heapRegion.hpp
g1MemoryPool.cpp g1CollectedHeap.inline.hpp
g1MemoryPool.cpp g1CollectedHeap.hpp
g1MemoryPool.cpp g1CollectorPolicy.hpp
g1MemoryPool.cpp g1MemoryPool.hpp
g1MemoryPool.hpp memoryUsage.hpp
g1MemoryPool.hpp memoryPool.hpp
g1OopClosures.inline.hpp concurrentMark.hpp
g1OopClosures.inline.hpp g1OopClosures.hpp
g1OopClosures.inline.hpp g1CollectedHeap.hpp
......@@ -303,6 +312,8 @@ heapRegionSeq.inline.hpp heapRegionSeq.hpp
klass.hpp g1OopClosures.hpp
memoryService.cpp g1MemoryPool.hpp
ptrQueue.cpp allocation.hpp
ptrQueue.cpp allocation.inline.hpp
ptrQueue.cpp mutex.hpp
......
/*
* Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
# include "incls/_precompiled.incl"
# include "incls/_g1MemoryPool.cpp.incl"
G1MemoryPoolSuper::G1MemoryPoolSuper(G1CollectedHeap* g1h,
const char* name,
size_t init_size,
size_t max_size,
bool support_usage_threshold) :
_g1h(g1h), CollectedMemoryPool(name,
MemoryPool::Heap,
init_size,
max_size,
support_usage_threshold) {
assert(UseG1GC, "sanity");
}
// See the comment at the top of g1MemoryPool.hpp
size_t G1MemoryPoolSuper::eden_space_committed(G1CollectedHeap* g1h) {
return eden_space_used(g1h);
}
// See the comment at the top of g1MemoryPool.hpp
size_t G1MemoryPoolSuper::eden_space_used(G1CollectedHeap* g1h) {
size_t young_list_length = g1h->young_list_length();
size_t eden_used = young_list_length * HeapRegion::GrainBytes;
size_t survivor_used = survivor_space_used(g1h);
eden_used = subtract_up_to_zero(eden_used, survivor_used);
return eden_used;
}
// See the comment at the top of g1MemoryPool.hpp
size_t G1MemoryPoolSuper::eden_space_max(G1CollectedHeap* g1h) {
return eden_space_committed(g1h);
}
// See the comment at the top of g1MemoryPool.hpp
size_t G1MemoryPoolSuper::survivor_space_committed(G1CollectedHeap* g1h) {
return survivor_space_used(g1h);
}
// See the comment at the top of g1MemoryPool.hpp
size_t G1MemoryPoolSuper::survivor_space_used(G1CollectedHeap* g1h) {
size_t survivor_num = g1h->g1_policy()->recorded_survivor_regions();
size_t survivor_used = survivor_num * HeapRegion::GrainBytes;
return survivor_used;
}
// See the comment at the top of g1MemoryPool.hpp
size_t G1MemoryPoolSuper::survivor_space_max(G1CollectedHeap* g1h) {
return survivor_space_committed(g1h);
}
// See the comment at the top of g1MemoryPool.hpp
size_t G1MemoryPoolSuper::old_space_committed(G1CollectedHeap* g1h) {
size_t committed = overall_committed(g1h);
size_t eden_committed = eden_space_committed(g1h);
size_t survivor_committed = survivor_space_committed(g1h);
committed = subtract_up_to_zero(committed, eden_committed);
committed = subtract_up_to_zero(committed, survivor_committed);
return committed;
}
// See the comment at the top of g1MemoryPool.hpp
size_t G1MemoryPoolSuper::old_space_used(G1CollectedHeap* g1h) {
size_t used = overall_used(g1h);
size_t eden_used = eden_space_used(g1h);
size_t survivor_used = survivor_space_used(g1h);
used = subtract_up_to_zero(used, eden_used);
used = subtract_up_to_zero(used, survivor_used);
return used;
}
// See the comment at the top of g1MemoryPool.hpp
size_t G1MemoryPoolSuper::old_space_max(G1CollectedHeap* g1h) {
size_t max = g1h->g1_reserved_obj_bytes();
size_t eden_max = eden_space_max(g1h);
size_t survivor_max = survivor_space_max(g1h);
max = subtract_up_to_zero(max, eden_max);
max = subtract_up_to_zero(max, survivor_max);
return max;
}
G1EdenPool::G1EdenPool(G1CollectedHeap* g1h) :
G1MemoryPoolSuper(g1h,
"G1 Eden",
eden_space_committed(g1h), /* init_size */
eden_space_max(g1h), /* max_size */
false /* support_usage_threshold */) {
}
MemoryUsage G1EdenPool::get_memory_usage() {
size_t maxSize = max_size();
size_t used = used_in_bytes();
size_t committed = eden_space_committed();
return MemoryUsage(initial_size(), used, committed, maxSize);
}
G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h) :
G1MemoryPoolSuper(g1h,
"G1 Survivor",
survivor_space_committed(g1h), /* init_size */
survivor_space_max(g1h), /* max_size */
false /* support_usage_threshold */) {
}
MemoryUsage G1SurvivorPool::get_memory_usage() {
size_t maxSize = max_size();
size_t used = used_in_bytes();
size_t committed = survivor_space_committed();
return MemoryUsage(initial_size(), used, committed, maxSize);
}
G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h) :
G1MemoryPoolSuper(g1h,
"G1 Old Gen",
old_space_committed(g1h), /* init_size */
old_space_max(g1h), /* max_size */
true /* support_usage_threshold */) {
}
MemoryUsage G1OldGenPool::get_memory_usage() {
size_t maxSize = max_size();
size_t used = used_in_bytes();
size_t committed = old_space_committed();
return MemoryUsage(initial_size(), used, committed, maxSize);
}
/*
* Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
class G1CollectedHeap;
// This file contains the three classes that represent the memory
// pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and
// G1OldGenPool. In G1, unlike our other GCs, we do not have a
// physical space for each of those spaces. Instead, we allocate
// regions for all three spaces out of a single pool of regions (that
// pool basically covers the entire heap). As a result, the eden,
// survivor, and old gen are considered logical spaces in G1, as each
// is a set of non-contiguous regions. This is also reflected in the
// way we map them to memory pools here. The easiest way to have done
// this would have been to map the entire G1 heap to a single memory
// pool. However, it's helpful to show how large the eden and survivor
// get, as this does affect the performance and behavior of G1. Which
// is why we introduce the three memory pools implemented here.
//
// The above approach inroduces a couple of challenging issues in the
// implementation of the three memory pools:
//
// 1) The used space calculation for a pool is not necessarily
// independent of the others. We can easily get from G1 the overall
// used space in the entire heap, the number of regions in the young
// generation (includes both eden and survivors), and the number of
// survivor regions. So, from that we calculate:
//
// survivor_used = survivor_num * region_size
// eden_used = young_region_num * region_size - survivor_used
// old_gen_used = overall_used - eden_used - survivor_used
//
// Note that survivor_used and eden_used are upper bounds. To get the
// actual value we would have to iterate over the regions and add up
// ->used(). But that'd be expensive. So, we'll accept some lack of
// accuracy for those two. But, we have to be careful when calculating
// old_gen_used, in case we subtract from overall_used more then the
// actual number and our result goes negative.
//
// 2) Calculating the used space is straightforward, as described
// above. However, how do we calculate the committed space, given that
// we allocate space for the eden, survivor, and old gen out of the
// same pool of regions? One way to do this is to use the used value
// as also the committed value for the eden and survivor spaces and
// then calculate the old gen committed space as follows:
//
// old_gen_committed = overall_committed - eden_committed - survivor_committed
//
// Maybe a better way to do that would be to calculate used for eden
// and survivor as a sum of ->used() over their regions and then
// calculate committed as region_num * region_size (i.e., what we use
// to calculate the used space now). This is something to consider
// in the future.
//
// 3) Another decision that is again not straightforward is what is
// the max size that each memory pool can grow to. Right now, we set
// that the committed size for the eden and the survivors and
// calculate the old gen max as follows (basically, it's a similar
// pattern to what we use for the committed space, as described
// above):
//
// old_gen_max = overall_max - eden_max - survivor_max
//
// 4) Now, there is a very subtle issue with all the above. The
// framework will call get_memory_usage() on the three pools
// asynchronously. As a result, each call might get a different value
// for, say, survivor_num which will yield inconsistent values for
// eden_used, survivor_used, and old_gen_used (as survivor_num is used
// in the calculation of all three). This would normally be
// ok. However, it's possible that this might cause the sum of
// eden_used, survivor_used, and old_gen_used to go over the max heap
// size and this seems to sometimes cause JConsole (and maybe other
// clients) to get confused. There's not a really an easy / clean
// solution to this problem, due to the asynchrounous nature of the
// framework.
// This class is shared by the three G1 memory pool classes
// (G1EdenPool, G1SurvivorPool, G1OldGenPool). Given that the way we
// calculate used / committed bytes for these three pools is related
// (see comment above), we put the calculations in this class so that
// we can easily share them among the subclasses.
class G1MemoryPoolSuper : public CollectedMemoryPool {
private:
G1CollectedHeap* _g1h;
// It returns x - y if x > y, 0 otherwise.
// As described in the comment above, some of the inputs to the
// calculations we have to do are obtained concurrently and hence
// may be inconsistent with each other. So, this provides a
// defensive way of performing the subtraction and avoids the value
// going negative (which would mean a very large result, given that
// the parameter are size_t).
static size_t subtract_up_to_zero(size_t x, size_t y) {
if (x > y) {
return x - y;
} else {
return 0;
}
}
protected:
// Would only be called from subclasses.
G1MemoryPoolSuper(G1CollectedHeap* g1h,
const char* name,
size_t init_size,
size_t max_size,
bool support_usage_threshold);
// The reason why all the code is in static methods is so that it
// can be safely called from the constructors of the subclasses.
static size_t overall_committed(G1CollectedHeap* g1h) {
return g1h->capacity();
}
static size_t overall_used(G1CollectedHeap* g1h) {
return g1h->used_unlocked();
}
static size_t eden_space_committed(G1CollectedHeap* g1h);
static size_t eden_space_used(G1CollectedHeap* g1h);
static size_t eden_space_max(G1CollectedHeap* g1h);
static size_t survivor_space_committed(G1CollectedHeap* g1h);
static size_t survivor_space_used(G1CollectedHeap* g1h);
static size_t survivor_space_max(G1CollectedHeap* g1h);
static size_t old_space_committed(G1CollectedHeap* g1h);
static size_t old_space_used(G1CollectedHeap* g1h);
static size_t old_space_max(G1CollectedHeap* g1h);
// The non-static versions are included for convenience.
size_t eden_space_committed() {
return eden_space_committed(_g1h);
}
size_t eden_space_used() {
return eden_space_used(_g1h);
}
size_t eden_space_max() {
return eden_space_max(_g1h);
}
size_t survivor_space_committed() {
return survivor_space_committed(_g1h);
}
size_t survivor_space_used() {
return survivor_space_used(_g1h);
}
size_t survivor_space_max() {
return survivor_space_max(_g1h);
}
size_t old_space_committed() {
return old_space_committed(_g1h);
}
size_t old_space_used() {
return old_space_used(_g1h);
}
size_t old_space_max() {
return old_space_max(_g1h);
}
};
// Memory pool that represents the G1 eden.
class G1EdenPool : public G1MemoryPoolSuper {
public:
G1EdenPool(G1CollectedHeap* g1h);
size_t used_in_bytes() {
return eden_space_used();
}
size_t max_size() {
return eden_space_max();
}
MemoryUsage get_memory_usage();
};
// Memory pool that represents the G1 survivor.
class G1SurvivorPool : public G1MemoryPoolSuper {
public:
G1SurvivorPool(G1CollectedHeap* g1h);
size_t used_in_bytes() {
return survivor_space_used();
}
size_t max_size() {
return survivor_space_max();
}
MemoryUsage get_memory_usage();
};
// Memory pool that represents the G1 old gen.
class G1OldGenPool : public G1MemoryPoolSuper {
public:
G1OldGenPool(G1CollectedHeap* g1h);
size_t used_in_bytes() {
return old_space_used();
}
size_t max_size() {
return old_space_max();
}
MemoryUsage get_memory_usage();
};
......@@ -72,6 +72,14 @@ GCMemoryManager* MemoryManager::get_psMarkSweep_memory_manager() {
return (GCMemoryManager*) new PSMarkSweepMemoryManager();
}
GCMemoryManager* MemoryManager::get_g1YoungGen_memory_manager() {
return (GCMemoryManager*) new G1YoungGenMemoryManager();
}
GCMemoryManager* MemoryManager::get_g1OldGen_memory_manager() {
return (GCMemoryManager*) new G1OldGenMemoryManager();
}
instanceOop MemoryManager::get_memory_manager_instance(TRAPS) {
// Must do an acquire so as to force ordering of subsequent
// loads from anything _memory_mgr_obj points to or implies.
......
......@@ -54,7 +54,9 @@ public:
ParNew,
ConcurrentMarkSweep,
PSScavenge,
PSMarkSweep
PSMarkSweep,
G1YoungGen,
G1OldGen
};
MemoryManager();
......@@ -85,6 +87,8 @@ public:
static GCMemoryManager* get_cms_memory_manager();
static GCMemoryManager* get_psScavenge_memory_manager();
static GCMemoryManager* get_psMarkSweep_memory_manager();
static GCMemoryManager* get_g1YoungGen_memory_manager();
static GCMemoryManager* get_g1OldGen_memory_manager();
};
......@@ -231,3 +235,21 @@ public:
MemoryManager::Name kind() { return MemoryManager::PSMarkSweep; }
const char* name() { return "PS MarkSweep"; }
};
class G1YoungGenMemoryManager : public GCMemoryManager {
private:
public:
G1YoungGenMemoryManager() : GCMemoryManager() {}
MemoryManager::Name kind() { return MemoryManager::G1YoungGen; }
const char* name() { return "G1 Young Generation"; }
};
class G1OldGenMemoryManager : public GCMemoryManager {
private:
public:
G1OldGenMemoryManager() : GCMemoryManager() {}
MemoryManager::Name kind() { return MemoryManager::G1OldGen; }
const char* name() { return "G1 Old Generation"; }
};
......@@ -60,8 +60,8 @@ void MemoryService::set_universe_heap(CollectedHeap* heap) {
break;
}
case CollectedHeap::G1CollectedHeap : {
G1CollectedHeap::g1_unimplemented();
return;
add_g1_heap_info(G1CollectedHeap::heap());
break;
}
#endif // SERIALGC
default: {
......@@ -164,6 +164,19 @@ void MemoryService::add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap)
add_psOld_memory_pool(heap->old_gen(), _major_gc_manager);
add_psPerm_memory_pool(heap->perm_gen(), _major_gc_manager);
}
void MemoryService::add_g1_heap_info(G1CollectedHeap* g1h) {
assert(UseG1GC, "sanity");
_minor_gc_manager = MemoryManager::get_g1YoungGen_memory_manager();
_major_gc_manager = MemoryManager::get_g1OldGen_memory_manager();
_managers_list->append(_minor_gc_manager);
_managers_list->append(_major_gc_manager);
add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);
add_g1OldGen_memory_pool(g1h, _major_gc_manager);
add_g1PermGen_memory_pool(g1h, _major_gc_manager);
}
#endif // SERIALGC
MemoryPool* MemoryService::add_gen(Generation* gen,
......@@ -384,6 +397,64 @@ void MemoryService::add_psPerm_memory_pool(PSPermGen* gen, MemoryManager* mgr) {
mgr->add_pool(perm_gen);
_pools_list->append(perm_gen);
}
void MemoryService::add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
MemoryManager* major_mgr,
MemoryManager* minor_mgr) {
assert(major_mgr != NULL && minor_mgr != NULL, "should have two managers");
G1EdenPool* eden = new G1EdenPool(g1h);
G1SurvivorPool* survivor = new G1SurvivorPool(g1h);
major_mgr->add_pool(eden);
major_mgr->add_pool(survivor);
minor_mgr->add_pool(eden);
minor_mgr->add_pool(survivor);
_pools_list->append(eden);
_pools_list->append(survivor);
}
void MemoryService::add_g1OldGen_memory_pool(G1CollectedHeap* g1h,
MemoryManager* mgr) {
assert(mgr != NULL, "should have one manager");
G1OldGenPool* old_gen = new G1OldGenPool(g1h);
mgr->add_pool(old_gen);
_pools_list->append(old_gen);
}
void MemoryService::add_g1PermGen_memory_pool(G1CollectedHeap* g1h,
MemoryManager* mgr) {
assert(mgr != NULL, "should have one manager");
CompactingPermGenGen* perm_gen = (CompactingPermGenGen*) g1h->perm_gen();
PermanentGenerationSpec* spec = perm_gen->spec();
size_t max_size = spec->max_size() - spec->read_only_size()
- spec->read_write_size();
MemoryPool* pool = add_space(perm_gen->unshared_space(),
"G1 Perm Gen",
false, /* is_heap */
max_size,
true /* support_usage_threshold */);
mgr->add_pool(pool);
// in case we support CDS in G1
if (UseSharedSpaces) {
pool = add_space(perm_gen->ro_space(),
"G1 Perm Gen [shared-ro]",
false, /* is_heap */
spec->read_only_size(),
true /* support_usage_threshold */);
mgr->add_pool(pool);
pool = add_space(perm_gen->rw_space(),
"G1 Perm Gen [shared-rw]",
false, /* is_heap */
spec->read_write_size(),
true /* support_usage_threshold */);
mgr->add_pool(pool);
}
}
#endif // SERIALGC
void MemoryService::add_code_heap_memory_pool(CodeHeap* heap) {
......
......@@ -40,6 +40,7 @@ class GenCollectedHeap;
class ParallelScavengeHeap;
class CompactingPermGenGen;
class CMSPermGenGen;
class G1CollectedHeap;
// VM Monitoring and Management Support
......@@ -88,6 +89,13 @@ private:
static void add_psPerm_memory_pool(PSPermGen* perm,
MemoryManager* mgr);
static void add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
MemoryManager* major_mgr,
MemoryManager* minor_mgr);
static void add_g1OldGen_memory_pool(G1CollectedHeap* g1h,
MemoryManager* mgr);
static void add_g1PermGen_memory_pool(G1CollectedHeap* g1h,
MemoryManager* mgr);
static MemoryPool* add_space(ContiguousSpace* space,
const char* name,
......@@ -111,6 +119,7 @@ private:
static void add_gen_collected_heap_info(GenCollectedHeap* heap);
static void add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap);
static void add_g1_heap_info(G1CollectedHeap* g1h);
public:
static void set_universe_heap(CollectedHeap* heap);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册