memoryService.cpp revision 0:a61af66fc99e
1/*
2 * Copyright 2003-2006 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/_memoryService.cpp.incl"
27
28GrowableArray<MemoryPool*>* MemoryService::_pools_list =
29  new (ResourceObj::C_HEAP) GrowableArray<MemoryPool*>(init_pools_list_size, true);
30GrowableArray<MemoryManager*>* MemoryService::_managers_list =
31  new (ResourceObj::C_HEAP) GrowableArray<MemoryManager*>(init_managers_list_size, true);
32
33GCMemoryManager* MemoryService::_minor_gc_manager = NULL;
34GCMemoryManager* MemoryService::_major_gc_manager = NULL;
35MemoryPool*      MemoryService::_code_heap_pool   = NULL;
36
37class GcThreadCountClosure: public ThreadClosure {
38 private:
39  int _count;
40 public:
41  GcThreadCountClosure() : _count(0) {};
42  void do_thread(Thread* thread);
43  int count() { return _count; }
44};
45
46void GcThreadCountClosure::do_thread(Thread* thread) {
47  _count++;
48}
49
50void MemoryService::set_universe_heap(CollectedHeap* heap) {
51  CollectedHeap::Name kind = heap->kind();
52  switch (kind) {
53    case CollectedHeap::GenCollectedHeap : {
54      add_gen_collected_heap_info(GenCollectedHeap::heap());
55      break;
56    }
57#ifndef SERIALGC
58    case CollectedHeap::ParallelScavengeHeap : {
59      add_parallel_scavenge_heap_info(ParallelScavengeHeap::heap());
60      break;
61    }
62#endif // SERIALGC
63    default: {
64      guarantee(false, "Not recognized kind of heap");
65    }
66  }
67
68  // set the GC thread count
69  GcThreadCountClosure gctcc;
70  heap->gc_threads_do(&gctcc);
71  int count = gctcc.count();
72  if (count > 0) {
73    _minor_gc_manager->set_num_gc_threads(count);
74    _major_gc_manager->set_num_gc_threads(count);
75  }
76
77  // All memory pools and memory managers are initialized.
78  //
79  _minor_gc_manager->initialize_gc_stat_info();
80  _major_gc_manager->initialize_gc_stat_info();
81}
82
83// Add memory pools for GenCollectedHeap
84// This function currently only supports two generations collected heap.
85// The collector for GenCollectedHeap will have two memory managers.
86void MemoryService::add_gen_collected_heap_info(GenCollectedHeap* heap) {
87  CollectorPolicy* policy = heap->collector_policy();
88
89  assert(policy->is_two_generation_policy(), "Only support two generations");
90  guarantee(heap->n_gens() == 2, "Only support two-generation heap");
91
92  TwoGenerationCollectorPolicy* two_gen_policy = policy->as_two_generation_policy();
93  if (two_gen_policy != NULL) {
94    GenerationSpec** specs = two_gen_policy->generations();
95    Generation::Name kind = specs[0]->name();
96    switch (kind) {
97      case Generation::DefNew:
98        _minor_gc_manager = MemoryManager::get_copy_memory_manager();
99        break;
100#ifndef SERIALGC
101      case Generation::ParNew:
102      case Generation::ASParNew:
103        _minor_gc_manager = MemoryManager::get_parnew_memory_manager();
104        break;
105#endif // SERIALGC
106      default:
107        guarantee(false, "Unrecognized generation spec");
108        break;
109    }
110    if (policy->is_mark_sweep_policy()) {
111      _major_gc_manager = MemoryManager::get_msc_memory_manager();
112#ifndef SERIALGC
113    } else if (policy->is_concurrent_mark_sweep_policy()) {
114      _major_gc_manager = MemoryManager::get_cms_memory_manager();
115#endif // SERIALGC
116    } else {
117      guarantee(false, "Unknown two-gen policy");
118    }
119  } else {
120    guarantee(false, "Non two-gen policy");
121  }
122  _managers_list->append(_minor_gc_manager);
123  _managers_list->append(_major_gc_manager);
124
125  add_generation_memory_pool(heap->get_gen(minor), _major_gc_manager, _minor_gc_manager);
126  add_generation_memory_pool(heap->get_gen(major), _major_gc_manager);
127
128  PermGen::Name name = policy->permanent_generation()->name();
129  switch (name) {
130    case PermGen::MarkSweepCompact: {
131      CompactingPermGenGen* perm_gen = (CompactingPermGenGen*) heap->perm_gen();
132      add_compact_perm_gen_memory_pool(perm_gen, _major_gc_manager);
133      break;
134    }
135#ifndef SERIALGC
136    case PermGen::ConcurrentMarkSweep: {
137      CMSPermGenGen* cms_gen = (CMSPermGenGen*) heap->perm_gen();
138      add_cms_perm_gen_memory_pool(cms_gen, _major_gc_manager);
139      break;
140    }
141#endif // SERIALGC
142    default:
143      guarantee(false, "Unrecognized perm generation");
144        break;
145  }
146}
147
148#ifndef SERIALGC
149// Add memory pools for ParallelScavengeHeap
150// This function currently only supports two generations collected heap.
151// The collector for ParallelScavengeHeap will have two memory managers.
152void MemoryService::add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap) {
153  // Two managers to keep statistics about _minor_gc_manager and _major_gc_manager GC.
154  _minor_gc_manager = MemoryManager::get_psScavenge_memory_manager();
155  _major_gc_manager = MemoryManager::get_psMarkSweep_memory_manager();
156  _managers_list->append(_minor_gc_manager);
157  _managers_list->append(_major_gc_manager);
158
159  add_psYoung_memory_pool(heap->young_gen(), _major_gc_manager, _minor_gc_manager);
160  add_psOld_memory_pool(heap->old_gen(), _major_gc_manager);
161  add_psPerm_memory_pool(heap->perm_gen(), _major_gc_manager);
162}
163#endif // SERIALGC
164
165MemoryPool* MemoryService::add_gen(Generation* gen,
166                                   const char* name,
167                                   bool is_heap,
168                                   bool support_usage_threshold) {
169
170  MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap);
171  GenerationPool* pool = new GenerationPool(gen, name, type, support_usage_threshold);
172  _pools_list->append(pool);
173  return (MemoryPool*) pool;
174}
175
176MemoryPool* MemoryService::add_space(ContiguousSpace* space,
177                                     const char* name,
178                                     bool is_heap,
179                                     size_t max_size,
180                                     bool support_usage_threshold) {
181  MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap);
182  ContiguousSpacePool* pool = new ContiguousSpacePool(space, name, type, max_size, support_usage_threshold);
183
184  _pools_list->append(pool);
185  return (MemoryPool*) pool;
186}
187
188MemoryPool* MemoryService::add_survivor_spaces(DefNewGeneration* gen,
189                                               const char* name,
190                                               bool is_heap,
191                                               size_t max_size,
192                                               bool support_usage_threshold) {
193  MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap);
194  SurvivorContiguousSpacePool* pool = new SurvivorContiguousSpacePool(gen, name, type, max_size, support_usage_threshold);
195
196  _pools_list->append(pool);
197  return (MemoryPool*) pool;
198}
199
200#ifndef SERIALGC
201MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space,
202                                         const char* name,
203                                         bool is_heap,
204                                         size_t max_size,
205                                         bool support_usage_threshold) {
206  MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap);
207  CompactibleFreeListSpacePool* pool = new CompactibleFreeListSpacePool(space, name, type, max_size, support_usage_threshold);
208  _pools_list->append(pool);
209  return (MemoryPool*) pool;
210}
211#endif // SERIALGC
212
213// Add memory pool(s) for one generation
214void MemoryService::add_generation_memory_pool(Generation* gen,
215                                               MemoryManager* major_mgr,
216                                               MemoryManager* minor_mgr) {
217  Generation::Name kind = gen->kind();
218  int index = _pools_list->length();
219
220  switch (kind) {
221    case Generation::DefNew: {
222      assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");
223      DefNewGeneration* young_gen = (DefNewGeneration*) gen;
224      // Add a memory pool for each space and young gen doesn't
225      // support low memory detection as it is expected to get filled up.
226      MemoryPool* eden = add_space(young_gen->eden(),
227                                   "Eden Space",
228                                   true, /* is_heap */
229                                   young_gen->max_eden_size(),
230                                   false /* support_usage_threshold */);
231      MemoryPool* survivor = add_survivor_spaces(young_gen,
232                                                 "Survivor Space",
233                                                 true, /* is_heap */
234                                                 young_gen->max_survivor_size(),
235                                                 false /* support_usage_threshold */);
236      break;
237    }
238
239#ifndef SERIALGC
240    case Generation::ParNew:
241    case Generation::ASParNew:
242    {
243      assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");
244      // Add a memory pool for each space and young gen doesn't
245      // support low memory detection as it is expected to get filled up.
246      ParNewGeneration* parnew_gen = (ParNewGeneration*) gen;
247      MemoryPool* eden = add_space(parnew_gen->eden(),
248                                   "Par Eden Space",
249                                   true /* is_heap */,
250                                   parnew_gen->max_eden_size(),
251                                   false /* support_usage_threshold */);
252      MemoryPool* survivor = add_survivor_spaces(parnew_gen,
253                                                 "Par Survivor Space",
254                                                 true, /* is_heap */
255                                                 parnew_gen->max_survivor_size(),
256                                                 false /* support_usage_threshold */);
257
258      break;
259    }
260#endif // SERIALGC
261
262    case Generation::MarkSweepCompact: {
263      assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager");
264      add_gen(gen,
265              "Tenured Gen",
266              true, /* is_heap */
267              true  /* support_usage_threshold */);
268      break;
269    }
270
271#ifndef SERIALGC
272    case Generation::ConcurrentMarkSweep:
273    case Generation::ASConcurrentMarkSweep:
274    {
275      assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager");
276      ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*) gen;
277      MemoryPool* pool = add_cms_space(cms->cmsSpace(),
278                                       "CMS Old Gen",
279                                       true, /* is_heap */
280                                       cms->reserved().byte_size(),
281                                       true  /* support_usage_threshold */);
282      break;
283    }
284#endif // SERIALGC
285
286    default:
287      assert(false, "should not reach here");
288      // no memory pool added for others
289      break;
290  }
291
292  assert(major_mgr != NULL, "Should have at least one manager");
293  // Link managers and the memory pools together
294  for (int i = index; i < _pools_list->length(); i++) {
295    MemoryPool* pool = _pools_list->at(i);
296    major_mgr->add_pool(pool);
297    if (minor_mgr != NULL) {
298      minor_mgr->add_pool(pool);
299    }
300  }
301}
302
303void MemoryService::add_compact_perm_gen_memory_pool(CompactingPermGenGen* perm_gen,
304                                                     MemoryManager* mgr) {
305  PermanentGenerationSpec* spec = perm_gen->spec();
306  size_t max_size = spec->max_size() - spec->read_only_size() - spec->read_write_size();
307  MemoryPool* pool = add_space(perm_gen->unshared_space(),
308                               "Perm Gen",
309                                false, /* is_heap */
310                                max_size,
311                                true   /* support_usage_threshold */);
312  mgr->add_pool(pool);
313  if (UseSharedSpaces) {
314    pool = add_space(perm_gen->ro_space(),
315                     "Perm Gen [shared-ro]",
316                     false, /* is_heap */
317                     spec->read_only_size(),
318                     true   /* support_usage_threshold */);
319    mgr->add_pool(pool);
320
321    pool = add_space(perm_gen->rw_space(),
322                     "Perm Gen [shared-rw]",
323                     false, /* is_heap */
324                     spec->read_write_size(),
325                     true   /* support_usage_threshold */);
326    mgr->add_pool(pool);
327  }
328}
329
330#ifndef SERIALGC
331void MemoryService::add_cms_perm_gen_memory_pool(CMSPermGenGen* cms_gen,
332                                                 MemoryManager* mgr) {
333
334  MemoryPool* pool = add_cms_space(cms_gen->cmsSpace(),
335                                   "CMS Perm Gen",
336                                   false, /* is_heap */
337                                   cms_gen->reserved().byte_size(),
338                                   true   /* support_usage_threshold */);
339  mgr->add_pool(pool);
340}
341
342void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) {
343  assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");
344
345  // Add a memory pool for each space and young gen doesn't
346  // support low memory detection as it is expected to get filled up.
347  EdenMutableSpacePool* eden = new EdenMutableSpacePool(gen,
348                                                        gen->eden_space(),
349                                                        "PS Eden Space",
350                                                        MemoryPool::Heap,
351                                                        false /* support_usage_threshold */);
352
353  SurvivorMutableSpacePool* survivor = new SurvivorMutableSpacePool(gen,
354                                                                    "PS Survivor Space",
355                                                                    MemoryPool::Heap,
356                                                                    false /* support_usage_threshold */);
357
358  major_mgr->add_pool(eden);
359  major_mgr->add_pool(survivor);
360  minor_mgr->add_pool(eden);
361  minor_mgr->add_pool(survivor);
362  _pools_list->append(eden);
363  _pools_list->append(survivor);
364}
365
366void MemoryService::add_psOld_memory_pool(PSOldGen* gen, MemoryManager* mgr) {
367  PSGenerationPool* old_gen = new PSGenerationPool(gen,
368                                                   "PS Old Gen",
369                                                   MemoryPool::Heap,
370                                                   true /* support_usage_threshold */);
371  mgr->add_pool(old_gen);
372  _pools_list->append(old_gen);
373}
374
375void MemoryService::add_psPerm_memory_pool(PSPermGen* gen, MemoryManager* mgr) {
376  PSGenerationPool* perm_gen = new PSGenerationPool(gen,
377                                                    "PS Perm Gen",
378                                                    MemoryPool::NonHeap,
379                                                    true /* support_usage_threshold */);
380  mgr->add_pool(perm_gen);
381  _pools_list->append(perm_gen);
382}
383#endif // SERIALGC
384
385void MemoryService::add_code_heap_memory_pool(CodeHeap* heap) {
386  _code_heap_pool = new CodeHeapPool(heap,
387                                     "Code Cache",
388                                     true /* support_usage_threshold */);
389  MemoryManager* mgr = MemoryManager::get_code_cache_memory_manager();
390  mgr->add_pool(_code_heap_pool);
391
392  _pools_list->append(_code_heap_pool);
393  _managers_list->append(mgr);
394}
395
396MemoryManager* MemoryService::get_memory_manager(instanceHandle mh) {
397  for (int i = 0; i < _managers_list->length(); i++) {
398    MemoryManager* mgr = _managers_list->at(i);
399    if (mgr->is_manager(mh)) {
400      return mgr;
401    }
402  }
403  return NULL;
404}
405
406MemoryPool* MemoryService::get_memory_pool(instanceHandle ph) {
407  for (int i = 0; i < _pools_list->length(); i++) {
408    MemoryPool* pool = _pools_list->at(i);
409    if (pool->is_pool(ph)) {
410      return pool;
411    }
412  }
413  return NULL;
414}
415
416void MemoryService::track_memory_usage() {
417  // Track the peak memory usage
418  for (int i = 0; i < _pools_list->length(); i++) {
419    MemoryPool* pool = _pools_list->at(i);
420    pool->record_peak_memory_usage();
421  }
422
423  // Detect low memory
424  LowMemoryDetector::detect_low_memory();
425}
426
427void MemoryService::track_memory_pool_usage(MemoryPool* pool) {
428  // Track the peak memory usage
429  pool->record_peak_memory_usage();
430
431  // Detect low memory
432  if (LowMemoryDetector::is_enabled(pool)) {
433    LowMemoryDetector::detect_low_memory(pool);
434  }
435}
436
437void MemoryService::gc_begin(bool fullGC) {
438  GCMemoryManager* mgr;
439  if (fullGC) {
440    mgr = _major_gc_manager;
441  } else {
442    mgr = _minor_gc_manager;
443  }
444  assert(mgr->is_gc_memory_manager(), "Sanity check");
445  mgr->gc_begin();
446
447  // Track the peak memory usage when GC begins
448  for (int i = 0; i < _pools_list->length(); i++) {
449    MemoryPool* pool = _pools_list->at(i);
450    pool->record_peak_memory_usage();
451  }
452}
453
454void MemoryService::gc_end(bool fullGC) {
455  GCMemoryManager* mgr;
456  if (fullGC) {
457    mgr = (GCMemoryManager*) _major_gc_manager;
458  } else {
459    mgr = (GCMemoryManager*) _minor_gc_manager;
460  }
461  assert(mgr->is_gc_memory_manager(), "Sanity check");
462
463  // register the GC end statistics and memory usage
464  mgr->gc_end();
465}
466
467void MemoryService::oops_do(OopClosure* f) {
468  int i;
469
470  for (i = 0; i < _pools_list->length(); i++) {
471    MemoryPool* pool = _pools_list->at(i);
472    pool->oops_do(f);
473  }
474  for (i = 0; i < _managers_list->length(); i++) {
475    MemoryManager* mgr = _managers_list->at(i);
476    mgr->oops_do(f);
477  }
478}
479
480bool MemoryService::set_verbose(bool verbose) {
481  MutexLocker m(Management_lock);
482  // verbose will be set to the previous value
483  bool succeed = CommandLineFlags::boolAtPut((char*)"PrintGC", &verbose, MANAGEMENT);
484  assert(succeed, "Setting PrintGC flag fails");
485  ClassLoadingService::reset_trace_class_unloading();
486
487  return verbose;
488}
489
490Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) {
491  klassOop k = Management::java_lang_management_MemoryUsage_klass(CHECK_NH);
492  instanceKlassHandle ik(THREAD, k);
493
494  instanceHandle obj = ik->allocate_instance_handle(CHECK_NH);
495
496  JavaValue result(T_VOID);
497  JavaCallArguments args(10);
498  args.push_oop(obj);                         // receiver
499  args.push_long(usage.init_size_as_jlong()); // Argument 1
500  args.push_long(usage.used_as_jlong());      // Argument 2
501  args.push_long(usage.committed_as_jlong()); // Argument 3
502  args.push_long(usage.max_size_as_jlong());  // Argument 4
503
504  JavaCalls::call_special(&result,
505                          ik,
506                          vmSymbolHandles::object_initializer_name(),
507                          vmSymbolHandles::long_long_long_long_void_signature(),
508                          &args,
509                          CHECK_NH);
510  return obj;
511}
512//
513// GC manager type depends on the type of Generation. Depending the space
514// availablity and vm option the gc uses major gc manager or minor gc
515// manager or both. The type of gc manager depends on the generation kind.
516// For DefNew, ParNew and ASParNew generation doing scavange gc uses minor
517// gc manager (so _fullGC is set to false ) and for other generation kind
518// DOing mark-sweep-compact uses major gc manager (so _fullGC is set
519// to true).
520TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind) {
521  switch (kind) {
522    case Generation::DefNew:
523#ifndef SERIALGC
524    case Generation::ParNew:
525    case Generation::ASParNew:
526#endif // SERIALGC
527      _fullGC=false;
528      break;
529    case Generation::MarkSweepCompact:
530#ifndef SERIALGC
531    case Generation::ConcurrentMarkSweep:
532    case Generation::ASConcurrentMarkSweep:
533#endif // SERIALGC
534      _fullGC=true;
535      break;
536    default:
537      assert(false, "Unrecognized gc generation kind.");
538  }
539  MemoryService::gc_begin(_fullGC);
540}
541TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC) {
542  _fullGC = fullGC;
543  MemoryService::gc_begin(_fullGC);
544}
545
546TraceMemoryManagerStats::~TraceMemoryManagerStats() {
547  MemoryService::gc_end(_fullGC);
548}
549