8215934: G1 Old Gen MemoryPool CollectionUsage.used values don't reflect mixed GC results

Mon, 28 Jan 2019 17:51:10 +0000

author
phh
date
Mon, 28 Jan 2019 17:51:10 +0000
changeset 9608
4b8584c24ff4
parent 9607
a9ab35a0f5cb
child 9609
28f68e5c6fb3

8215934: G1 Old Gen MemoryPool CollectionUsage.used values don't reflect mixed GC results
Summary: Memory pools can now be optional collection participants, e.g., G1 Old Gen in an incremental collection.
Reviewed-by: tschatzl, jcbeyler, andrew

src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp file | annotate | diff | comparison | revisions
src/share/vm/services/memoryManager.cpp file | annotate | diff | comparison | revisions
src/share/vm/services/memoryManager.hpp file | annotate | diff | comparison | revisions
src/share/vm/services/memoryService.cpp file | annotate | diff | comparison | revisions
src/share/vm/services/memoryService.hpp file | annotate | diff | comparison | revisions
test/gc/TestMemoryMXBeansAndPoolsPresence.java file | annotate | diff | comparison | revisions
test/gc/g1/mixedgc/TestOldGenCollectionUsage.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Tue Jan 08 04:55:25 2019 +0000
     1.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Mon Jan 28 17:51:10 2019 +0000
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -9541,6 +9541,7 @@
    1.11      case CMSCollector::InitialMarking:
    1.12        initialize(true  /* fullGC */ ,
    1.13                   cause /* cause of the GC */,
    1.14 +                 true  /* allMemoryPoolsAffected */,
    1.15                   true  /* recordGCBeginTime */,
    1.16                   true  /* recordPreGCUsage */,
    1.17                   false /* recordPeakUsage */,
    1.18 @@ -9553,6 +9554,7 @@
    1.19      case CMSCollector::FinalMarking:
    1.20        initialize(true  /* fullGC */ ,
    1.21                   cause /* cause of the GC */,
    1.22 +                 true  /* allMemoryPoolsAffected */,
    1.23                   false /* recordGCBeginTime */,
    1.24                   false /* recordPreGCUsage */,
    1.25                   false /* recordPeakUsage */,
    1.26 @@ -9565,6 +9567,7 @@
    1.27      case CMSCollector::Sweeping:
    1.28        initialize(true  /* fullGC */ ,
    1.29                   cause /* cause of the GC */,
    1.30 +                 true  /* allMemoryPoolsAffected */,
    1.31                   false /* recordGCBeginTime */,
    1.32                   false /* recordPreGCUsage */,
    1.33                   true  /* recordPeakUsage */,
     2.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Tue Jan 08 04:55:25 2019 +0000
     2.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Mon Jan 28 17:51:10 2019 +0000
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -4008,7 +4008,8 @@
    2.11      log_gc_header();
    2.12  
    2.13      TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
    2.14 -    TraceMemoryManagerStats tms(false /* fullGC */, gc_cause());
    2.15 +    TraceMemoryManagerStats tms(false /* fullGC */, gc_cause(),
    2.16 +                                yc_type() == Mixed /* allMemoryPoolsAffected */);
    2.17  
    2.18      // If the secondary_free_list is not empty, append it to the
    2.19      // free_list. No need to wait for the cleanup operation to finish;
     3.1 --- a/src/share/vm/services/memoryManager.cpp	Tue Jan 08 04:55:25 2019 +0000
     3.2 +++ b/src/share/vm/services/memoryManager.cpp	Mon Jan 28 17:51:10 2019 +0000
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -49,13 +49,15 @@
    3.11    (void)const_cast<instanceOop&>(_memory_mgr_obj = instanceOop(NULL));
    3.12  }
    3.13  
    3.14 -void MemoryManager::add_pool(MemoryPool* pool) {
    3.15 -  assert(_num_pools < MemoryManager::max_num_pools, "_num_pools exceeds the max");
    3.16 -  if (_num_pools < MemoryManager::max_num_pools) {
    3.17 -    _pools[_num_pools] = pool;
    3.18 +int MemoryManager::add_pool(MemoryPool* pool) {
    3.19 +  int index = _num_pools;
    3.20 +  assert(index < MemoryManager::max_num_pools, "_num_pools exceeds the max");
    3.21 +  if (index < MemoryManager::max_num_pools) {
    3.22 +    _pools[index] = pool;
    3.23      _num_pools++;
    3.24    }
    3.25    pool->add_manager(this);
    3.26 +  return index;
    3.27  }
    3.28  
    3.29  MemoryManager* MemoryManager::get_code_cache_memory_manager() {
    3.30 @@ -217,6 +219,15 @@
    3.31    delete _current_gc_stat;
    3.32  }
    3.33  
    3.34 +void GCMemoryManager::add_pool(MemoryPool* pool) {
    3.35 +  add_pool(pool, true);
    3.36 +}
    3.37 +
    3.38 +void GCMemoryManager::add_pool(MemoryPool* pool, bool always_affected_by_gc) {
    3.39 +  int index = MemoryManager::add_pool(pool);
    3.40 +  _pool_always_affected_by_gc[index] = always_affected_by_gc;
    3.41 +}
    3.42 +
    3.43  void GCMemoryManager::initialize_gc_stat_info() {
    3.44    assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools");
    3.45    _last_gc_stat = new(ResourceObj::C_HEAP, mtGC) GCStatInfo(MemoryService::num_memory_pools());
    3.46 @@ -266,7 +277,8 @@
    3.47  void GCMemoryManager::gc_end(bool recordPostGCUsage,
    3.48                               bool recordAccumulatedGCTime,
    3.49                               bool recordGCEndTime, bool countCollection,
    3.50 -                             GCCause::Cause cause) {
    3.51 +                             GCCause::Cause cause,
    3.52 +                             bool allMemoryPoolsAffected) {
    3.53    if (recordAccumulatedGCTime) {
    3.54      _accumulated_timer.stop();
    3.55    }
    3.56 @@ -304,8 +316,11 @@
    3.57        MemoryUsage usage = pool->get_memory_usage();
    3.58  
    3.59        // Compare with GC usage threshold
    3.60 -      pool->set_last_collection_usage(usage);
    3.61 -      LowMemoryDetector::detect_after_gc_memory(pool);
    3.62 +      if (allMemoryPoolsAffected || pool_always_affected_by_gc(i)) {
    3.63 +        // Compare with GC usage threshold
    3.64 +        pool->set_last_collection_usage(usage);
    3.65 +        LowMemoryDetector::detect_after_gc_memory(pool);
    3.66 +      }
    3.67      }
    3.68    }
    3.69  
     4.1 --- a/src/share/vm/services/memoryManager.hpp	Tue Jan 08 04:55:25 2019 +0000
     4.2 +++ b/src/share/vm/services/memoryManager.hpp	Mon Jan 28 17:51:10 2019 +0000
     4.3 @@ -1,5 +1,5 @@
     4.4  /*
     4.5 - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     4.6 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
     4.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.8   *
     4.9   * This code is free software; you can redistribute it and/or modify it
    4.10 @@ -41,11 +41,12 @@
    4.11  class OopClosure;
    4.12  
    4.13  class MemoryManager : public CHeapObj<mtInternal> {
    4.14 -private:
    4.15 +protected:
    4.16    enum {
    4.17      max_num_pools = 10
    4.18    };
    4.19  
    4.20 +private:
    4.21    MemoryPool* _pools[max_num_pools];
    4.22    int         _num_pools;
    4.23  
    4.24 @@ -75,7 +76,7 @@
    4.25      return _pools[index];
    4.26    }
    4.27  
    4.28 -  void add_pool(MemoryPool* pool);
    4.29 +  int add_pool(MemoryPool* pool);
    4.30  
    4.31    bool is_manager(instanceHandle mh)     { return mh() == _memory_mgr_obj; }
    4.32  
    4.33 @@ -177,10 +178,20 @@
    4.34    GCStatInfo*  _current_gc_stat;
    4.35    int          _num_gc_threads;
    4.36    volatile bool _notification_enabled;
    4.37 +  bool         _pool_always_affected_by_gc[MemoryManager::max_num_pools];
    4.38 +
    4.39  public:
    4.40    GCMemoryManager();
    4.41    ~GCMemoryManager();
    4.42  
    4.43 +  void add_pool(MemoryPool* pool);
    4.44 +  void add_pool(MemoryPool* pool, bool always_affected_by_gc);
    4.45 +
    4.46 +  bool pool_always_affected_by_gc(int index) {
    4.47 +    assert(index >= 0 && index < num_memory_pools(), "Invalid index");
    4.48 +    return _pool_always_affected_by_gc[index];
    4.49 +  }
    4.50 +
    4.51    void   initialize_gc_stat_info();
    4.52  
    4.53    bool   is_gc_memory_manager()         { return true; }
    4.54 @@ -192,7 +203,8 @@
    4.55    void   gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,
    4.56                    bool recordAccumulatedGCTime);
    4.57    void   gc_end(bool recordPostGCUsage, bool recordAccumulatedGCTime,
    4.58 -                bool recordGCEndTime, bool countCollection, GCCause::Cause cause);
    4.59 +                bool recordGCEndTime, bool countCollection, GCCause::Cause cause,
    4.60 +                bool allMemoryPoolsAffected);
    4.61  
    4.62    void        reset_gc_stat()   { _num_collections = 0; _accumulated_timer.reset(); }
    4.63  
     5.1 --- a/src/share/vm/services/memoryService.cpp	Tue Jan 08 04:55:25 2019 +0000
     5.2 +++ b/src/share/vm/services/memoryService.cpp	Mon Jan 28 17:51:10 2019 +0000
     5.3 @@ -1,5 +1,5 @@
     5.4  /*
     5.5 - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     5.6 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
     5.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.8   *
     5.9   * This code is free software; you can redistribute it and/or modify it
    5.10 @@ -187,7 +187,7 @@
    5.11    _managers_list->append(_major_gc_manager);
    5.12  
    5.13    add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);
    5.14 -  add_g1OldGen_memory_pool(g1h, _major_gc_manager);
    5.15 +  add_g1OldGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);
    5.16  }
    5.17  #endif // INCLUDE_ALL_GCS
    5.18  
    5.19 @@ -241,8 +241,8 @@
    5.20  
    5.21  // Add memory pool(s) for one generation
    5.22  void MemoryService::add_generation_memory_pool(Generation* gen,
    5.23 -                                               MemoryManager* major_mgr,
    5.24 -                                               MemoryManager* minor_mgr) {
    5.25 +                                               GCMemoryManager* major_mgr,
    5.26 +                                               GCMemoryManager* minor_mgr) {
    5.27    guarantee(gen != NULL, "No generation for memory pool");
    5.28    Generation::Name kind = gen->kind();
    5.29    int index = _pools_list->length();
    5.30 @@ -332,7 +332,9 @@
    5.31  
    5.32  
    5.33  #if INCLUDE_ALL_GCS
    5.34 -void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) {
    5.35 +void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen,
    5.36 +                                            GCMemoryManager* major_mgr,
    5.37 +                                            GCMemoryManager* minor_mgr) {
    5.38    assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");
    5.39  
    5.40    // Add a memory pool for each space and young gen doesn't
    5.41 @@ -356,7 +358,7 @@
    5.42    _pools_list->append(survivor);
    5.43  }
    5.44  
    5.45 -void MemoryService::add_psOld_memory_pool(PSOldGen* gen, MemoryManager* mgr) {
    5.46 +void MemoryService::add_psOld_memory_pool(PSOldGen* gen, GCMemoryManager* mgr) {
    5.47    PSGenerationPool* old_gen = new PSGenerationPool(gen,
    5.48                                                     "PS Old Gen",
    5.49                                                     MemoryPool::Heap,
    5.50 @@ -366,8 +368,8 @@
    5.51  }
    5.52  
    5.53  void MemoryService::add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
    5.54 -                                               MemoryManager* major_mgr,
    5.55 -                                               MemoryManager* minor_mgr) {
    5.56 +                                               GCMemoryManager* major_mgr,
    5.57 +                                               GCMemoryManager* minor_mgr) {
    5.58    assert(major_mgr != NULL && minor_mgr != NULL, "should have two managers");
    5.59  
    5.60    G1EdenPool* eden = new G1EdenPool(g1h);
    5.61 @@ -382,11 +384,13 @@
    5.62  }
    5.63  
    5.64  void MemoryService::add_g1OldGen_memory_pool(G1CollectedHeap* g1h,
    5.65 -                                             MemoryManager* mgr) {
    5.66 -  assert(mgr != NULL, "should have one manager");
    5.67 +                                             GCMemoryManager* major_mgr,
    5.68 +                                             GCMemoryManager* minor_mgr) {
    5.69 +  assert(major_mgr != NULL && minor_mgr != NULL, "should have two managers");
    5.70  
    5.71    G1OldGenPool* old_gen = new G1OldGenPool(g1h);
    5.72 -  mgr->add_pool(old_gen);
    5.73 +  major_mgr->add_pool(old_gen);
    5.74 +  minor_mgr->add_pool(old_gen, false /* always_affected_by_gc */);
    5.75    _pools_list->append(old_gen);
    5.76  }
    5.77  #endif // INCLUDE_ALL_GCS
    5.78 @@ -484,7 +488,8 @@
    5.79  void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage,
    5.80                             bool recordAccumulatedGCTime,
    5.81                             bool recordGCEndTime, bool countCollection,
    5.82 -                           GCCause::Cause cause) {
    5.83 +                           GCCause::Cause cause,
    5.84 +                           bool allMemoryPoolsAffected) {
    5.85  
    5.86    GCMemoryManager* mgr;
    5.87    if (fullGC) {
    5.88 @@ -496,7 +501,7 @@
    5.89  
    5.90    // register the GC end statistics and memory usage
    5.91    mgr->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,
    5.92 -              countCollection, cause);
    5.93 +              countCollection, cause, allMemoryPoolsAffected);
    5.94  }
    5.95  
    5.96  void MemoryService::oops_do(OopClosure* f) {
    5.97 @@ -573,10 +578,11 @@
    5.98    }
    5.99    // this has to be called in a stop the world pause and represent
   5.100    // an entire gc pause, start to finish:
   5.101 -  initialize(_fullGC, cause,true, true, true, true, true, true, true);
   5.102 +  initialize(_fullGC, cause, true, true, true, true, true, true, true, true);
   5.103  }
   5.104  TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC,
   5.105                                                   GCCause::Cause cause,
   5.106 +                                                 bool allMemoryPoolsAffected,
   5.107                                                   bool recordGCBeginTime,
   5.108                                                   bool recordPreGCUsage,
   5.109                                                   bool recordPeakUsage,
   5.110 @@ -584,7 +590,8 @@
   5.111                                                   bool recordAccumulatedGCTime,
   5.112                                                   bool recordGCEndTime,
   5.113                                                   bool countCollection) {
   5.114 -    initialize(fullGC, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage,
   5.115 +  initialize(fullGC, cause, allMemoryPoolsAffected,
   5.116 +             recordGCBeginTime, recordPreGCUsage, recordPeakUsage,
   5.117               recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,
   5.118               countCollection);
   5.119  }
   5.120 @@ -593,6 +600,7 @@
   5.121  // the MemoryService
   5.122  void TraceMemoryManagerStats::initialize(bool fullGC,
   5.123                                           GCCause::Cause cause,
   5.124 +                                         bool allMemoryPoolsAffected,
   5.125                                           bool recordGCBeginTime,
   5.126                                           bool recordPreGCUsage,
   5.127                                           bool recordPeakUsage,
   5.128 @@ -601,6 +609,7 @@
   5.129                                           bool recordGCEndTime,
   5.130                                           bool countCollection) {
   5.131    _fullGC = fullGC;
   5.132 +  _allMemoryPoolsAffected = allMemoryPoolsAffected;
   5.133    _recordGCBeginTime = recordGCBeginTime;
   5.134    _recordPreGCUsage = recordPreGCUsage;
   5.135    _recordPeakUsage = recordPeakUsage;
   5.136 @@ -616,5 +625,5 @@
   5.137  
   5.138  TraceMemoryManagerStats::~TraceMemoryManagerStats() {
   5.139    MemoryService::gc_end(_fullGC, _recordPostGCUsage, _recordAccumulatedGCTime,
   5.140 -                        _recordGCEndTime, _countCollection, _cause);
   5.141 +                        _recordGCEndTime, _countCollection, _cause, _allMemoryPoolsAffected);
   5.142  }
     6.1 --- a/src/share/vm/services/memoryService.hpp	Tue Jan 08 04:55:25 2019 +0000
     6.2 +++ b/src/share/vm/services/memoryService.hpp	Mon Jan 28 17:51:10 2019 +0000
     6.3 @@ -1,5 +1,5 @@
     6.4  /*
     6.5 - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     6.6 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
     6.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.8   *
     6.9   * This code is free software; you can redistribute it and/or modify it
    6.10 @@ -77,25 +77,26 @@
    6.11    static MemoryPool*                    _compressed_class_pool;
    6.12  
    6.13    static void add_generation_memory_pool(Generation* gen,
    6.14 -                                         MemoryManager* major_mgr,
    6.15 -                                         MemoryManager* minor_mgr);
    6.16 +                                         GCMemoryManager* major_mgr,
    6.17 +                                         GCMemoryManager* minor_mgr);
    6.18    static void add_generation_memory_pool(Generation* gen,
    6.19 -                                         MemoryManager* major_mgr) {
    6.20 +                                         GCMemoryManager* major_mgr) {
    6.21      add_generation_memory_pool(gen, major_mgr, NULL);
    6.22    }
    6.23  
    6.24  
    6.25    static void add_psYoung_memory_pool(PSYoungGen* gen,
    6.26 -                                      MemoryManager* major_mgr,
    6.27 -                                      MemoryManager* minor_mgr);
    6.28 +                                      GCMemoryManager* major_mgr,
    6.29 +                                      GCMemoryManager* minor_mgr);
    6.30    static void add_psOld_memory_pool(PSOldGen* gen,
    6.31 -                                    MemoryManager* mgr);
    6.32 +                                    GCMemoryManager* mgr);
    6.33  
    6.34    static void add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
    6.35 -                                         MemoryManager* major_mgr,
    6.36 -                                         MemoryManager* minor_mgr);
    6.37 +                                         GCMemoryManager* major_mgr,
    6.38 +                                         GCMemoryManager* minor_mgr);
    6.39    static void add_g1OldGen_memory_pool(G1CollectedHeap* g1h,
    6.40 -                                       MemoryManager* mgr);
    6.41 +                                       GCMemoryManager* major_mgr,
    6.42 +                                       GCMemoryManager* minor_mgr);
    6.43  
    6.44    static MemoryPool* add_space(ContiguousSpace* space,
    6.45                                 const char* name,
    6.46 @@ -162,7 +163,8 @@
    6.47    static void gc_end(bool fullGC, bool recordPostGCUsage,
    6.48                       bool recordAccumulatedGCTime,
    6.49                       bool recordGCEndTime, bool countCollection,
    6.50 -                     GCCause::Cause cause);
    6.51 +                     GCCause::Cause cause,
    6.52 +                     bool allMemoryPoolsAffected);
    6.53  
    6.54  
    6.55    static void oops_do(OopClosure* f);
    6.56 @@ -185,6 +187,7 @@
    6.57  class TraceMemoryManagerStats : public StackObj {
    6.58  private:
    6.59    bool         _fullGC;
    6.60 +  bool         _allMemoryPoolsAffected;
    6.61    bool         _recordGCBeginTime;
    6.62    bool         _recordPreGCUsage;
    6.63    bool         _recordPeakUsage;
    6.64 @@ -197,6 +200,7 @@
    6.65    TraceMemoryManagerStats() {}
    6.66    TraceMemoryManagerStats(bool fullGC,
    6.67                            GCCause::Cause cause,
    6.68 +                          bool allMemoryPoolsAffected = true,
    6.69                            bool recordGCBeginTime = true,
    6.70                            bool recordPreGCUsage = true,
    6.71                            bool recordPeakUsage = true,
    6.72 @@ -207,6 +211,7 @@
    6.73  
    6.74    void initialize(bool fullGC,
    6.75                    GCCause::Cause cause,
    6.76 +                  bool allMemoryPoolsAffected,
    6.77                    bool recordGCBeginTime,
    6.78                    bool recordPreGCUsage,
    6.79                    bool recordPeakUsage,
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/gc/TestMemoryMXBeansAndPoolsPresence.java	Mon Jan 28 17:51:10 2019 +0000
     7.3 @@ -0,0 +1,101 @@
     7.4 +/*
     7.5 + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + *
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.
    7.11 + *
    7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.15 + * version 2 for more details (a copy is included in the LICENSE file that
    7.16 + * accompanied this code).
    7.17 + *
    7.18 + * You should have received a copy of the GNU General Public License version
    7.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.21 + *
    7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    7.23 + * or visit www.oracle.com if you need additional information or have any
    7.24 + * questions.
    7.25 + */
    7.26 +
    7.27 +/* @test TestMemoryMXBeansAndPoolsPresence
    7.28 + * @key gc
    7.29 + * @bug 8191564
    7.30 + * @summary Tests that GarbageCollectorMXBeans and GC MemoryPools are created.
    7.31 + * @library /testlibrary
    7.32 + * @requires vm.gc == null
    7.33 + * @run main/othervm -XX:+UseParallelGC TestMemoryMXBeansAndPoolsPresence Parallel
    7.34 + * @run main/othervm -XX:+UseSerialGC TestMemoryMXBeansAndPoolsPresence Serial
    7.35 + * @run main/othervm -XX:+UseConcMarkSweepGC TestMemoryMXBeansAndPoolsPresence CMS
    7.36 + * @run main/othervm -XX:+UseG1GC TestMemoryMXBeansAndPoolsPresence G1
    7.37 + */
    7.38 +
    7.39 +import java.util.List;
    7.40 +import java.util.ArrayList;
    7.41 +import java.lang.management.*;
    7.42 +import java.util.stream.*;
    7.43 +
    7.44 +import com.oracle.java.testlibrary.Asserts;
    7.45 +
    7.46 +class GCBeanDescription {
    7.47 +    public String name;
    7.48 +    public String[] poolNames;
    7.49 +
    7.50 +    public GCBeanDescription(String name, String[] poolNames) {
    7.51 +        this.name = name;
    7.52 +        this.poolNames = poolNames;
    7.53 +    }
    7.54 +}
    7.55 +
    7.56 +public class TestMemoryMXBeansAndPoolsPresence {
    7.57 +    public static void test(GCBeanDescription... expectedBeans) {
    7.58 +        List<MemoryPoolMXBean> memoryPools = ManagementFactory.getMemoryPoolMXBeans();
    7.59 +
    7.60 +        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
    7.61 +        Asserts.assertEQ(expectedBeans.length, gcBeans.size());
    7.62 +
    7.63 +        for (GCBeanDescription desc : expectedBeans) {
    7.64 +            List<GarbageCollectorMXBean> beans = gcBeans.stream()
    7.65 +                                                        .filter(b -> b.getName().equals(desc.name))
    7.66 +                                                        .collect(Collectors.toList());
    7.67 +            Asserts.assertEQ(beans.size(), 1);
    7.68 +
    7.69 +            GarbageCollectorMXBean bean = beans.get(0);
    7.70 +            Asserts.assertEQ(desc.name, bean.getName());
    7.71 +
    7.72 +            String[] pools = bean.getMemoryPoolNames();
    7.73 +            Asserts.assertEQ(desc.poolNames.length, pools.length);
    7.74 +            for (int i = 0; i < desc.poolNames.length; i++) {
    7.75 +                Asserts.assertEQ(desc.poolNames[i], pools[i]);
    7.76 +            }
    7.77 +        }
    7.78 +    }
    7.79 +
    7.80 +    public static void main(String[] args) {
    7.81 +        switch (args[0]) {
    7.82 +            case "G1":
    7.83 +                test(new GCBeanDescription("G1 Young Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"}),
    7.84 +                     new GCBeanDescription("G1 Old Generation",   new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"}));
    7.85 +                break;
    7.86 +            case "CMS":
    7.87 +                test(new GCBeanDescription("ParNew",              new String[] {"Par Eden Space", "Par Survivor Space"}),
    7.88 +                     new GCBeanDescription("ConcurrentMarkSweep", new String[] {"Par Eden Space", "Par Survivor Space", "CMS Old Gen"}));
    7.89 +                break;
    7.90 +            case "Parallel":
    7.91 +                test(new GCBeanDescription("PS Scavenge",         new String[] {"PS Eden Space", "PS Survivor Space"}),
    7.92 +                     new GCBeanDescription("PS MarkSweep",        new String[] {"PS Eden Space", "PS Survivor Space", "PS Old Gen"}));
    7.93 +                break;
    7.94 +            case "Serial":
    7.95 +                test(new GCBeanDescription("Copy",              new String[] {"Eden Space", "Survivor Space"}),
    7.96 +                     new GCBeanDescription("MarkSweepCompact",  new String[] {"Eden Space", "Survivor Space", "Tenured Gen"}));
    7.97 +                break;
    7.98 +            default:
    7.99 +                Asserts.assertTrue(false);
   7.100 +                break;
   7.101 +
   7.102 +        }
   7.103 +    }
   7.104 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/gc/g1/mixedgc/TestOldGenCollectionUsage.java	Mon Jan 28 17:51:10 2019 +0000
     8.3 @@ -0,0 +1,232 @@
     8.4 +/*
     8.5 + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + *
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General Public License version 2 only, as
    8.10 + * published by the Free Software Foundation.
    8.11 + *
    8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    8.15 + * version 2 for more details (a copy is included in the LICENSE file that
    8.16 + * accompanied this code).
    8.17 + *
    8.18 + * You should have received a copy of the GNU General Public License version
    8.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.21 + *
    8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    8.23 + * or visit www.oracle.com if you need additional information or have any
    8.24 + * questions.
    8.25 + */
    8.26 +
    8.27 +/*
    8.28 + * @test TestOldGenCollectionUsage.java
    8.29 + * @bug 8195115
    8.30 + * @summary G1 Old Gen's CollectionUsage.used is zero after mixed GC which is incorrect
    8.31 + * @key gc
    8.32 + * @requires vm.gc=="G1" | vm.gc=="null"
    8.33 + * @requires vm.opt.MaxGCPauseMillis == "null"
    8.34 + * @library /testlibrary /testlibrary/whitebox
    8.35 + * @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.WhiteBox TestOldGenCollectionUsage
    8.36 + * @run main ClassFileInstaller sun.hotspot.WhiteBox
    8.37 + *                              sun.hotspot.WhiteBox$WhiteBoxPermission
    8.38 + * @run main/othervm -Xbootclasspath/a:. -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
    8.39 + *                   -XX:+WhiteBoxAPI -verbose:gc -XX:SurvivorRatio=1 -Xmx14m -Xms14m -XX:MaxTenuringThreshold=1
    8.40 + *                   -XX:InitiatingHeapOccupancyPercent=100 -XX:G1MixedGCCountTarget=4 -XX:MaxGCPauseMillis=30000
    8.41 + *                   -XX:G1HeapRegionSize=1m -XX:G1HeapWastePercent=0 -XX:G1MixedGCLiveThresholdPercent=100
    8.42 + *                   TestOldGenCollectionUsage
    8.43 + */
    8.44 +
    8.45 +import com.oracle.java.testlibrary.Asserts;
    8.46 +import sun.hotspot.WhiteBox;
    8.47 +
    8.48 +import java.util.ArrayList;
    8.49 +import java.util.List;
    8.50 +import java.util.Collections;
    8.51 +
    8.52 +import java.lang.management.*;
    8.53 +
    8.54 +// 8195115 says that for the "G1 Old Gen" MemoryPool, CollectionUsage.used
    8.55 +// is zero for G1 after a mixed collection, which is incorrect.
    8.56 +
    8.57 +public class TestOldGenCollectionUsage {
    8.58 +
    8.59 +    private String poolName = "G1 Old Gen";
    8.60 +    private String collectorName = "G1 Young Generation";
    8.61 +
    8.62 +    public static void main(String [] args) throws Exception {
    8.63 +        TestOldGenCollectionUsage t = new TestOldGenCollectionUsage();
    8.64 +        t.run();
    8.65 +    }
    8.66 +
    8.67 +    public TestOldGenCollectionUsage() {
    8.68 +        System.out.println("Monitor G1 Old Gen pool with G1 Young Generation collector.");
    8.69 +    }
    8.70 +
    8.71 +    public void run() {
    8.72 +        // Find memory pool and collector
    8.73 +        List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
    8.74 +        MemoryPoolMXBean pool = null;
    8.75 +        boolean foundPool = false;
    8.76 +        for (int i = 0; i < pools.size(); i++) {
    8.77 +            pool = pools.get(i);
    8.78 +            String name = pool.getName();
    8.79 +            if (name.contains(poolName)) {
    8.80 +                System.out.println("Found pool: " + name);
    8.81 +                foundPool = true;
    8.82 +                break;
    8.83 +            }
    8.84 +        }
    8.85 +        if (!foundPool) {
    8.86 +            throw new RuntimeException(poolName + " not found, test with -XX:+UseG1GC");
    8.87 +        }
    8.88 +
    8.89 +        List<GarbageCollectorMXBean> collectors = ManagementFactory.getGarbageCollectorMXBeans();
    8.90 +        GarbageCollectorMXBean collector = null;
    8.91 +        boolean foundCollector = false;
    8.92 +        for (int i = 0; i < collectors.size(); i++) {
    8.93 +            collector = collectors.get(i);
    8.94 +            String name = collector.getName();
    8.95 +            if (name.contains(collectorName)) {
    8.96 +                System.out.println("Found collector: " + name);
    8.97 +                foundCollector = true;
    8.98 +                break;
    8.99 +            }
   8.100 +        }
   8.101 +        if (!foundCollector) {
   8.102 +            throw new RuntimeException(collectorName + " not found, test with -XX:+UseG1GC");
   8.103 +        }
   8.104 +
   8.105 +        MixedGCProvoker gcProvoker = new MixedGCProvoker();
   8.106 +        gcProvoker.allocateOldObjects();
   8.107 +
   8.108 +        // Verify no non-zero result was stored
   8.109 +        long usage = pool.getCollectionUsage().getUsed();
   8.110 +        System.out.println(poolName + ": usage after GC = " + usage);
   8.111 +        if (usage > 0) {
   8.112 +            throw new RuntimeException("Premature mixed collections(s)");
   8.113 +        }
   8.114 +
   8.115 +        // Verify that collections were done
   8.116 +        long collectionCount = collector.getCollectionCount();
   8.117 +        System.out.println(collectorName + ": collection count = "
   8.118 +                           + collectionCount);
   8.119 +        long collectionTime = collector.getCollectionTime();
   8.120 +        System.out.println(collectorName + ": collection time  = "
   8.121 +                           + collectionTime);
   8.122 +        if (collectionCount <= 0) {
   8.123 +            throw new RuntimeException("Collection count <= 0");
   8.124 +        }
   8.125 +        if (collectionTime <= 0) {
   8.126 +            throw new RuntimeException("Collector has not run");
   8.127 +        }
   8.128 +
   8.129 +        gcProvoker.provokeMixedGC();
   8.130 +
   8.131 +        usage = pool.getCollectionUsage().getUsed();
   8.132 +        System.out.println(poolName + ": usage after GC = " + usage);
   8.133 +        if (usage <= 0) {
   8.134 +            throw new RuntimeException(poolName + " found with zero usage");
   8.135 +        }
   8.136 +
   8.137 +        long newCollectionCount = collector.getCollectionCount();
   8.138 +        System.out.println(collectorName + ": collection count = "
   8.139 +                           + newCollectionCount);
   8.140 +        long newCollectionTime = collector.getCollectionTime();
   8.141 +        System.out.println(collectorName + ": collection time  = "
   8.142 +                           + newCollectionTime);
   8.143 +        if (newCollectionCount <= collectionCount) {
   8.144 +            throw new RuntimeException("No new collection");
   8.145 +        }
   8.146 +        if (newCollectionTime <= collectionTime) {
   8.147 +            throw new RuntimeException("Collector has not run some more");
   8.148 +        }
   8.149 +
   8.150 +        System.out.println("Test passed.");
   8.151 +    }
   8.152 +
   8.153 +    /**
   8.154 +     * Utility class to guarantee a mixed GC. The class allocates several arrays and
   8.155 +     * promotes them to the oldgen. After that it tries to provoke mixed GC by
   8.156 +     * allocating new objects.
   8.157 +     *
   8.158 +     * The necessary condition for guaranteed mixed GC is running MixedGCProvoker is
   8.159 +     * running in VM with the following flags: -XX:MaxTenuringThreshold=1 -Xms12M
   8.160 +     * -Xmx12M -XX:G1MixedGCLiveThresholdPercent=100 -XX:G1HeapWastePercent=0
   8.161 +     * -XX:G1HeapRegionSize=1m
   8.162 +     */
   8.163 +    public class MixedGCProvoker {
   8.164 +        private final WhiteBox WB = WhiteBox.getWhiteBox();
   8.165 +        private final List<byte[]> liveOldObjects = new ArrayList<>();
   8.166 +        private final List<byte[]> newObjects = new ArrayList<>();
   8.167 +
   8.168 +        public static final int ALLOCATION_SIZE = 20000;
   8.169 +        public static final int ALLOCATION_COUNT = 15;
   8.170 +
   8.171 +        public void allocateOldObjects() {
   8.172 +            List<byte[]> deadOldObjects = new ArrayList<>();
   8.173 +            // Allocates buffer and promotes it to the old gen. Mix live and dead old
   8.174 +            // objects
   8.175 +            for (int i = 0; i < ALLOCATION_COUNT; ++i) {
   8.176 +                liveOldObjects.add(new byte[ALLOCATION_SIZE * 5]);
   8.177 +                deadOldObjects.add(new byte[ALLOCATION_SIZE * 5]);
   8.178 +            }
   8.179 +
   8.180 +            // Do two young collections, MaxTenuringThreshold=1 will force promotion.
   8.181 +            // G1HeapRegionSize=1m guarantees that old gen regions will be filled.
   8.182 +            WB.youngGC();
   8.183 +            WB.youngGC();
   8.184 +            // Check it is promoted & keep alive
   8.185 +            Asserts.assertTrue(WB.isObjectInOldGen(liveOldObjects),
   8.186 +                               "List of the objects is suppose to be in OldGen");
   8.187 +            Asserts.assertTrue(WB.isObjectInOldGen(deadOldObjects),
   8.188 +                               "List of the objects is suppose to be in OldGen");
   8.189 +        }
   8.190 +
   8.191 +        /**
   8.192 +         * Waits until Concurent Mark Cycle finishes
   8.193 +         * @param wb  Whitebox instance
   8.194 +         * @param sleepTime sleep time
   8.195 +         */
   8.196 +        private void waitTillCMCFinished(int sleepTime) {
   8.197 +            while (WB.g1InConcurrentMark()) {
   8.198 +                if (sleepTime > -1) {
   8.199 +                    try {
   8.200 +                        Thread.sleep(sleepTime);
   8.201 +                    } catch (InterruptedException e) {
   8.202 +                        System.out.println("Got InterruptedException while waiting for ConcMarkCycle to finish");
   8.203 +                    }
   8.204 +                }
   8.205 +            }
   8.206 +        }
   8.207 +
   8.208 +        public void provokeMixedGC() {
   8.209 +            waitTillCMCFinished(0);
   8.210 +            WB.g1StartConcMarkCycle();
   8.211 +            waitTillCMCFinished(0);
   8.212 +            WB.youngGC();
   8.213 +
   8.214 +            System.out.println("Allocating new objects to provoke mixed GC");
   8.215 +            // Provoke a mixed collection. G1MixedGCLiveThresholdPercent=100
   8.216 +            // guarantees that full old gen regions will be included.
   8.217 +            for (int i = 0; i < (ALLOCATION_COUNT * 20); i++) {
   8.218 +                try {
   8.219 +                    newObjects.add(new byte[ALLOCATION_SIZE]);
   8.220 +                } catch (OutOfMemoryError e) {
   8.221 +                    newObjects.clear();
   8.222 +                    WB.youngGC();
   8.223 +                    WB.youngGC();
   8.224 +                    System.out.println("OutOfMemoryError is reported, stop allocating new objects");
   8.225 +                    break;
   8.226 +                }
   8.227 +            }
   8.228 +            // check that liveOldObjects still alive
   8.229 +            Asserts.assertTrue(WB.isObjectInOldGen(liveOldObjects),
   8.230 +                               "List of the objects is suppose to be in OldGen");
   8.231 +        }
   8.232 +
   8.233 +    }
   8.234 +
   8.235 +}

mercurial