提交 a8687702 编写于 作者: K kevinw

6581734: CMS Old Gen's collection usage is zero after GC which is incorrect

Summary: Management code enabled for use by a concurrent collector.
Reviewed-by: mchung, ysr
上级 9aa6edd7
......@@ -1970,6 +1970,9 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
_intra_sweep_estimate.padded_average());
}
{
TraceCMSMemoryManagerStats();
}
GenMarkSweep::invoke_at_safepoint(_cmsGen->level(),
ref_processor(), clear_all_soft_refs);
#ifdef ASSERT
......@@ -3420,6 +3423,7 @@ CMSPhaseAccounting::~CMSPhaseAccounting() {
void CMSCollector::checkpointRootsInitial(bool asynch) {
assert(_collectorState == InitialMarking, "Wrong collector state");
check_correct_thread_executing();
TraceCMSMemoryManagerStats tms(_collectorState);
ReferenceProcessor* rp = ref_processor();
SpecializationStats::clear();
assert(_restart_addr == NULL, "Control point invariant");
......@@ -4753,6 +4757,7 @@ void CMSCollector::checkpointRootsFinal(bool asynch,
// world is stopped at this checkpoint
assert(SafepointSynchronize::is_at_safepoint(),
"world should be stopped");
TraceCMSMemoryManagerStats tms(_collectorState);
verify_work_stacks_empty();
verify_overflow_empty();
......@@ -5854,6 +5859,8 @@ void CMSCollector::sweep(bool asynch) {
verify_work_stacks_empty();
verify_overflow_empty();
increment_sweep_count();
TraceCMSMemoryManagerStats tms(_collectorState);
_inter_sweep_timer.stop();
_inter_sweep_estimate.sample(_inter_sweep_timer.seconds());
size_policy()->avg_cms_free_at_sweep()->sample(_cmsGen->free());
......@@ -9126,3 +9133,57 @@ size_t MarkDeadObjectsClosure::do_blk(HeapWord* addr) {
}
return res;
}
TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(CMSCollector::CollectorState phase): TraceMemoryManagerStats() {
switch (phase) {
case CMSCollector::InitialMarking:
initialize(true /* fullGC */ ,
true /* recordGCBeginTime */,
true /* recordPreGCUsage */,
false /* recordPeakUsage */,
false /* recordPostGCusage */,
true /* recordAccumulatedGCTime */,
false /* recordGCEndTime */,
false /* countCollection */ );
break;
case CMSCollector::FinalMarking:
initialize(true /* fullGC */ ,
false /* recordGCBeginTime */,
false /* recordPreGCUsage */,
false /* recordPeakUsage */,
false /* recordPostGCusage */,
true /* recordAccumulatedGCTime */,
false /* recordGCEndTime */,
false /* countCollection */ );
break;
case CMSCollector::Sweeping:
initialize(true /* fullGC */ ,
false /* recordGCBeginTime */,
false /* recordPreGCUsage */,
true /* recordPeakUsage */,
true /* recordPostGCusage */,
false /* recordAccumulatedGCTime */,
true /* recordGCEndTime */,
true /* countCollection */ );
break;
default:
ShouldNotReachHere();
}
}
// when bailing out of cms in concurrent mode failure
TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(): TraceMemoryManagerStats() {
initialize(true /* fullGC */ ,
true /* recordGCBeginTime */,
true /* recordPreGCUsage */,
true /* recordPeakUsage */,
true /* recordPostGCusage */,
true /* recordAccumulatedGCTime */,
true /* recordGCEndTime */,
true /* countCollection */ );
}
......@@ -507,6 +507,7 @@ class CMSCollector: public CHeapObj {
friend class VM_CMS_Operation;
friend class VM_CMS_Initial_Mark;
friend class VM_CMS_Final_Remark;
friend class TraceCMSMemoryManagerStats;
private:
jlong _time_of_last_gc;
......@@ -1858,3 +1859,11 @@ public:
_dead_bit_map(dead_bit_map) {}
size_t do_blk(HeapWord* addr);
};
class TraceCMSMemoryManagerStats : public TraceMemoryManagerStats {
public:
TraceCMSMemoryManagerStats(CMSCollector::CollectorState phase);
TraceCMSMemoryManagerStats();
};
......@@ -149,6 +149,7 @@ concurrentMarkSweepGeneration.cpp isGCActiveMark.hpp
concurrentMarkSweepGeneration.cpp iterator.hpp
concurrentMarkSweepGeneration.cpp java.hpp
concurrentMarkSweepGeneration.cpp jvmtiExport.hpp
concurrentMarkSweepGeneration.cpp memoryService.hpp
concurrentMarkSweepGeneration.cpp oop.inline.hpp
concurrentMarkSweepGeneration.cpp parNewGeneration.hpp
concurrentMarkSweepGeneration.cpp referencePolicy.hpp
......@@ -165,6 +166,7 @@ concurrentMarkSweepGeneration.hpp gSpaceCounters.hpp
concurrentMarkSweepGeneration.hpp gcStats.hpp
concurrentMarkSweepGeneration.hpp generation.hpp
concurrentMarkSweepGeneration.hpp generationCounters.hpp
concurrentMarkSweepGeneration.hpp memoryService.hpp
concurrentMarkSweepGeneration.hpp mutexLocker.hpp
concurrentMarkSweepGeneration.hpp taskqueue.hpp
concurrentMarkSweepGeneration.hpp virtualspace.hpp
......
......@@ -1900,16 +1900,15 @@ JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat))
// Get the GCMemoryManager
GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK);
if (mgr->last_gc_stat() == NULL) {
gc_stat->gc_index = 0;
return;
}
// Make a copy of the last GC statistics
// GC may occur while constructing the last GC information
int num_pools = MemoryService::num_memory_pools();
GCStatInfo* stat = new GCStatInfo(num_pools);
stat->copy_stat(mgr->last_gc_stat());
if (mgr->get_last_gc_stat(stat) == 0) {
gc_stat->gc_index = 0;
return;
}
gc_stat->gc_index = stat->gc_index();
gc_stat->start_time = Management::ticks_to_ms(stat->start_time());
......
......@@ -166,17 +166,6 @@ GCStatInfo::~GCStatInfo() {
FREE_C_HEAP_ARRAY(MemoryUsage*, _after_gc_usage_array);
}
void GCStatInfo::copy_stat(GCStatInfo* stat) {
set_index(stat->gc_index());
set_start_time(stat->start_time());
set_end_time(stat->end_time());
assert(_usage_array_size == stat->usage_array_size(), "Must have same array size");
for (int i = 0; i < _usage_array_size; i++) {
set_before_gc_usage(i, stat->before_gc_usage_for_pool(i));
set_after_gc_usage(i, stat->after_gc_usage_for_pool(i));
}
}
void GCStatInfo::set_gc_usage(int pool_index, MemoryUsage usage, bool before_gc) {
MemoryUsage* gc_usage_array;
if (before_gc) {
......@@ -187,67 +176,129 @@ void GCStatInfo::set_gc_usage(int pool_index, MemoryUsage usage, bool before_gc)
gc_usage_array[pool_index] = usage;
}
void GCStatInfo::clear() {
_index = 0;
_start_time = 0L;
_end_time = 0L;
size_t len = _usage_array_size * sizeof(MemoryUsage);
memset(_before_gc_usage_array, 0, len);
memset(_after_gc_usage_array, 0, len);
}
GCMemoryManager::GCMemoryManager() : MemoryManager() {
_num_collections = 0;
_last_gc_stat = NULL;
_last_gc_lock = new Mutex(Mutex::leaf, "_last_gc_lock", true);
_current_gc_stat = NULL;
_num_gc_threads = 1;
}
GCMemoryManager::~GCMemoryManager() {
delete _last_gc_stat;
delete _last_gc_lock;
delete _current_gc_stat;
}
void GCMemoryManager::initialize_gc_stat_info() {
assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools");
_last_gc_stat = new GCStatInfo(MemoryService::num_memory_pools());
_current_gc_stat = new GCStatInfo(MemoryService::num_memory_pools());
// tracking concurrent collections we need two objects: one to update, and one to
// hold the publicly available "last (completed) gc" information.
}
void GCMemoryManager::gc_begin() {
assert(_last_gc_stat != NULL, "Just checking");
_accumulated_timer.start();
_num_collections++;
_last_gc_stat->set_index(_num_collections);
_last_gc_stat->set_start_time(Management::timestamp());
// Keep memory usage of all memory pools
for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
MemoryPool* pool = MemoryService::get_memory_pool(i);
MemoryUsage usage = pool->get_memory_usage();
_last_gc_stat->set_before_gc_usage(i, usage);
HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin,
name(), strlen(name()),
pool->name(), strlen(pool->name()),
usage.init_size(), usage.used(),
usage.committed(), usage.max_size());
void GCMemoryManager::gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,
bool recordAccumulatedGCTime) {
assert(_last_gc_stat != NULL && _current_gc_stat != NULL, "Just checking");
if (recordAccumulatedGCTime) {
_accumulated_timer.start();
}
// _num_collections now increases in gc_end, to count completed collections
if (recordGCBeginTime) {
_current_gc_stat->set_index(_num_collections+1);
_current_gc_stat->set_start_time(Management::timestamp());
}
if (recordPreGCUsage) {
// Keep memory usage of all memory pools
for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
MemoryPool* pool = MemoryService::get_memory_pool(i);
MemoryUsage usage = pool->get_memory_usage();
_current_gc_stat->set_before_gc_usage(i, usage);
HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin,
name(), strlen(name()),
pool->name(), strlen(pool->name()),
usage.init_size(), usage.used(),
usage.committed(), usage.max_size());
}
}
}
void GCMemoryManager::gc_end() {
_accumulated_timer.stop();
_last_gc_stat->set_end_time(Management::timestamp());
// A collector MUST, even if it does not complete for some reason,
// make a TraceMemoryManagerStats object where countCollection is true,
// to ensure the current gc stat is placed in _last_gc_stat.
void GCMemoryManager::gc_end(bool recordPostGCUsage,
bool recordAccumulatedGCTime,
bool recordGCEndTime, bool countCollection) {
if (recordAccumulatedGCTime) {
_accumulated_timer.stop();
}
if (recordGCEndTime) {
_current_gc_stat->set_end_time(Management::timestamp());
}
int i;
// keep the last gc statistics for all memory pools
for (i = 0; i < MemoryService::num_memory_pools(); i++) {
MemoryPool* pool = MemoryService::get_memory_pool(i);
MemoryUsage usage = pool->get_memory_usage();
if (recordPostGCUsage) {
int i;
// keep the last gc statistics for all memory pools
for (i = 0; i < MemoryService::num_memory_pools(); i++) {
MemoryPool* pool = MemoryService::get_memory_pool(i);
MemoryUsage usage = pool->get_memory_usage();
HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end,
name(), strlen(name()),
pool->name(), strlen(pool->name()),
usage.init_size(), usage.used(),
usage.committed(), usage.max_size());
HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end,
name(), strlen(name()),
pool->name(), strlen(pool->name()),
usage.init_size(), usage.used(),
usage.committed(), usage.max_size());
_last_gc_stat->set_after_gc_usage(i, usage);
}
_current_gc_stat->set_after_gc_usage(i, usage);
}
// Set last collection usage of the memory pools managed by this collector
for (i = 0; i < num_memory_pools(); i++) {
MemoryPool* pool = get_memory_pool(i);
MemoryUsage usage = pool->get_memory_usage();
// Set last collection usage of the memory pools managed by this collector
for (i = 0; i < num_memory_pools(); i++) {
MemoryPool* pool = get_memory_pool(i);
MemoryUsage usage = pool->get_memory_usage();
// Compare with GC usage threshold
pool->set_last_collection_usage(usage);
LowMemoryDetector::detect_after_gc_memory(pool);
}
}
if (countCollection) {
_num_collections++;
// alternately update two objects making one public when complete
{
MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
GCStatInfo *tmp = _last_gc_stat;
_last_gc_stat = _current_gc_stat;
_current_gc_stat = tmp;
// reset the current stat for diagnosability purposes
_current_gc_stat->clear();
}
}
}
// Compare with GC usage threshold
pool->set_last_collection_usage(usage);
LowMemoryDetector::detect_after_gc_memory(pool);
size_t GCMemoryManager::get_last_gc_stat(GCStatInfo* dest) {
MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
if (_last_gc_stat->gc_index() != 0) {
dest->set_index(_last_gc_stat->gc_index());
dest->set_start_time(_last_gc_stat->start_time());
dest->set_end_time(_last_gc_stat->end_time());
assert(dest->usage_array_size() == _last_gc_stat->usage_array_size(),
"Must have same array size");
size_t len = dest->usage_array_size() * sizeof(MemoryUsage);
memcpy(dest->before_gc_usage_array(), _last_gc_stat->before_gc_usage_array(), len);
memcpy(dest->after_gc_usage_array(), _last_gc_stat->after_gc_usage_array(), len);
}
return _last_gc_stat->gc_index();
}
......@@ -131,6 +131,9 @@ public:
return _after_gc_usage_array[pool_index];
}
MemoryUsage* before_gc_usage_array() { return _before_gc_usage_array; }
MemoryUsage* after_gc_usage_array() { return _after_gc_usage_array; }
void set_index(size_t index) { _index = index; }
void set_start_time(jlong time) { _start_time = time; }
void set_end_time(jlong time) { _end_time = time; }
......@@ -143,7 +146,7 @@ public:
set_gc_usage(pool_index, usage, false /* after gc */);
}
void copy_stat(GCStatInfo* stat);
void clear();
};
class GCMemoryManager : public MemoryManager {
......@@ -153,6 +156,8 @@ private:
elapsedTimer _accumulated_timer;
elapsedTimer _gc_timer; // for measuring every GC duration
GCStatInfo* _last_gc_stat;
Mutex* _last_gc_lock;
GCStatInfo* _current_gc_stat;
int _num_gc_threads;
public:
GCMemoryManager();
......@@ -166,11 +171,16 @@ public:
int num_gc_threads() { return _num_gc_threads; }
void set_num_gc_threads(int count) { _num_gc_threads = count; }
void gc_begin();
void gc_end();
void gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,
bool recordAccumulatedGCTime);
void gc_end(bool recordPostGCUsage, bool recordAccumulatedGCTime,
bool recordGCEndTime, bool countCollection);
void reset_gc_stat() { _num_collections = 0; _accumulated_timer.reset(); }
GCStatInfo* last_gc_stat() { return _last_gc_stat; }
// Copy out _last_gc_stat to the given destination, returning
// the collection count. Zero signifies no gc has taken place.
size_t get_last_gc_stat(GCStatInfo* dest);
virtual MemoryManager::Name kind() = 0;
};
......
......@@ -509,7 +509,10 @@ void MemoryService::track_memory_pool_usage(MemoryPool* pool) {
}
}
void MemoryService::gc_begin(bool fullGC) {
void MemoryService::gc_begin(bool fullGC, bool recordGCBeginTime,
bool recordAccumulatedGCTime,
bool recordPreGCUsage, bool recordPeakUsage) {
GCMemoryManager* mgr;
if (fullGC) {
mgr = _major_gc_manager;
......@@ -517,16 +520,21 @@ void MemoryService::gc_begin(bool fullGC) {
mgr = _minor_gc_manager;
}
assert(mgr->is_gc_memory_manager(), "Sanity check");
mgr->gc_begin();
mgr->gc_begin(recordGCBeginTime, recordPreGCUsage, recordAccumulatedGCTime);
// Track the peak memory usage when GC begins
for (int i = 0; i < _pools_list->length(); i++) {
MemoryPool* pool = _pools_list->at(i);
pool->record_peak_memory_usage();
if (recordPeakUsage) {
for (int i = 0; i < _pools_list->length(); i++) {
MemoryPool* pool = _pools_list->at(i);
pool->record_peak_memory_usage();
}
}
}
void MemoryService::gc_end(bool fullGC) {
void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage,
bool recordAccumulatedGCTime,
bool recordGCEndTime, bool countCollection) {
GCMemoryManager* mgr;
if (fullGC) {
mgr = (GCMemoryManager*) _major_gc_manager;
......@@ -536,7 +544,8 @@ void MemoryService::gc_end(bool fullGC) {
assert(mgr->is_gc_memory_manager(), "Sanity check");
// register the GC end statistics and memory usage
mgr->gc_end();
mgr->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,
countCollection);
}
void MemoryService::oops_do(OopClosure* f) {
......@@ -585,12 +594,12 @@ Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) {
return obj;
}
//
// GC manager type depends on the type of Generation. Depending the space
// availablity and vm option the gc uses major gc manager or minor gc
// GC manager type depends on the type of Generation. Depending on the space
// availablity and vm options the gc uses major gc manager or minor gc
// manager or both. The type of gc manager depends on the generation kind.
// For DefNew, ParNew and ASParNew generation doing scavange gc uses minor
// gc manager (so _fullGC is set to false ) and for other generation kind
// DOing mark-sweep-compact uses major gc manager (so _fullGC is set
// For DefNew, ParNew and ASParNew generation doing scavenge gc uses minor
// gc manager (so _fullGC is set to false ) and for other generation kinds
// doing mark-sweep-compact uses major gc manager (so _fullGC is set
// to true).
TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind) {
switch (kind) {
......@@ -611,13 +620,48 @@ TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind) {
default:
assert(false, "Unrecognized gc generation kind.");
}
MemoryService::gc_begin(_fullGC);
// this has to be called in a stop the world pause and represent
// an entire gc pause, start to finish:
initialize(_fullGC, true, true, true, true, true, true, true);
}
TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC,
bool recordGCBeginTime,
bool recordPreGCUsage,
bool recordPeakUsage,
bool recordPostGCUsage,
bool recordAccumulatedGCTime,
bool recordGCEndTime,
bool countCollection) {
initialize(fullGC, recordGCBeginTime, recordPreGCUsage, recordPeakUsage,
recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,
countCollection);
}
TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC) {
// for a subclass to create then initialize an instance before invoking
// the MemoryService
void TraceMemoryManagerStats::initialize(bool fullGC,
bool recordGCBeginTime,
bool recordPreGCUsage,
bool recordPeakUsage,
bool recordPostGCUsage,
bool recordAccumulatedGCTime,
bool recordGCEndTime,
bool countCollection) {
_fullGC = fullGC;
MemoryService::gc_begin(_fullGC);
_recordGCBeginTime = recordGCBeginTime;
_recordPreGCUsage = recordPreGCUsage;
_recordPeakUsage = recordPeakUsage;
_recordPostGCUsage = recordPostGCUsage;
_recordAccumulatedGCTime = recordAccumulatedGCTime;
_recordGCEndTime = recordGCEndTime;
_countCollection = countCollection;
MemoryService::gc_begin(_fullGC, _recordGCBeginTime, _recordAccumulatedGCTime,
_recordPreGCUsage, _recordPeakUsage);
}
TraceMemoryManagerStats::~TraceMemoryManagerStats() {
MemoryService::gc_end(_fullGC);
MemoryService::gc_end(_fullGC, _recordPostGCUsage, _recordAccumulatedGCTime,
_recordGCEndTime, _countCollection);
}
......@@ -149,8 +149,13 @@ public:
}
static void track_memory_pool_usage(MemoryPool* pool);
static void gc_begin(bool fullGC);
static void gc_end(bool fullGC);
static void gc_begin(bool fullGC, bool recordGCBeginTime,
bool recordAccumulatedGCTime,
bool recordPreGCUsage, bool recordPeakUsage);
static void gc_end(bool fullGC, bool recordPostGCUsage,
bool recordAccumulatedGCTime,
bool recordGCEndTime, bool countCollection);
static void oops_do(OopClosure* f);
......@@ -164,8 +169,34 @@ public:
class TraceMemoryManagerStats : public StackObj {
private:
bool _fullGC;
bool _recordGCBeginTime;
bool _recordPreGCUsage;
bool _recordPeakUsage;
bool _recordPostGCUsage;
bool _recordAccumulatedGCTime;
bool _recordGCEndTime;
bool _countCollection;
public:
TraceMemoryManagerStats(bool fullGC);
TraceMemoryManagerStats() {}
TraceMemoryManagerStats(bool fullGC,
bool recordGCBeginTime = true,
bool recordPreGCUsage = true,
bool recordPeakUsage = true,
bool recordPostGCUsage = true,
bool recordAccumulatedGCTime = true,
bool recordGCEndTime = true,
bool countCollection = true);
void initialize(bool fullGC,
bool recordGCBeginTime,
bool recordPreGCUsage,
bool recordPeakUsage,
bool recordPostGCUsage,
bool recordAccumulatedGCTime,
bool recordGCEndTime,
bool countCollection);
TraceMemoryManagerStats(Generation::Name kind);
~TraceMemoryManagerStats();
};
/*
* Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test Test6581734.java
* @bug 6581734
* @summary CMS Old Gen's collection usage is zero after GC which is incorrect
* @run main/othervm -Xmx512m -verbose:gc -XX:+UseConcMarkSweepGC Test6581734
*
*/
import java.util.*;
import java.lang.management.*;
// 6581734 states that memory pool usage via the mbean is wrong
// for CMS (zero, even after a collection).
//
// 6580448 states that the collection count similarly is wrong
// (stays at zero for CMS collections)
// -- closed as dup of 6581734 as the same fix resolves both.
public class Test6581734 {
private String poolName = "CMS";
private String collectorName = "ConcurrentMarkSweep";
public static void main(String [] args) {
Test6581734 t = null;
if (args.length==2) {
t = new Test6581734(args[0], args[1]);
} else {
System.out.println("Defaulting to monitor CMS pool and collector.");
t = new Test6581734();
}
t.run();
}
public Test6581734(String pool, String collector) {
poolName = pool;
collectorName = collector;
}
public Test6581734() {
}
public void run() {
// Use some memory, enough that we expect collections should
// have happened.
// Must run with options to ensure no stop the world full GC,
// but e.g. at least one CMS cycle.
allocationWork(300*1024*1024);
System.out.println("Done allocationWork");
// Verify some non-zero results are stored.
List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
int poolsFound = 0;
int poolsWithStats = 0;
for (int i=0; i<pools.size(); i++) {
MemoryPoolMXBean pool = pools.get(i);
String name = pool.getName();
System.out.println("found pool: " + name);
if (name.contains(poolName)) {
long usage = pool.getCollectionUsage().getUsed();
System.out.println(name + ": usage after GC = " + usage);
poolsFound++;
if (usage > 0) {
poolsWithStats++;
}
}
}
if (poolsFound == 0) {
throw new RuntimeException("No matching memory pools found: test with -XX:+UseConcMarkSweepGC");
}
List<GarbageCollectorMXBean> collectors = ManagementFactory.getGarbageCollectorMXBeans();
int collectorsFound = 0;
int collectorsWithTime= 0;
for (int i=0; i<collectors.size(); i++) {
GarbageCollectorMXBean collector = collectors.get(i);
String name = collector.getName();
System.out.println("found collector: " + name);
if (name.contains(collectorName)) {
collectorsFound++;
System.out.println(name + ": collection count = "
+ collector.getCollectionCount());
System.out.println(name + ": collection time = "
+ collector.getCollectionTime());
if (collector.getCollectionCount() <= 0) {
throw new RuntimeException("collection count <= 0");
}
if (collector.getCollectionTime() > 0) {
collectorsWithTime++;
}
}
}
// verify:
if (poolsWithStats < poolsFound) {
throw new RuntimeException("pools found with zero stats");
}
if (collectorsWithTime<collectorsFound) {
throw new RuntimeException("collectors found with zero time";
}
System.out.println("Test passed.");
}
public void allocationWork(long target) {
long sizeAllocated = 0;
List list = new LinkedList();
long delay = 50;
long count = 0;
while (sizeAllocated < target) {
int size = 1024*1024;
byte [] alloc = new byte[size];
if (count % 2 == 0) {
list.add(alloc);
sizeAllocated+=size;
System.out.print(".");
}
try { Thread.sleep(delay); } catch (InterruptedException ie) { }
count++;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册