src/hotspot/share/memory/metaspace.cpp
changeset 47802 18dccdc438d7
parent 47654 dbd1f4f276ba
child 47808 57752bd5d1b4
equal deleted inserted replaced
47801:c7b50c23ea71 47802:18dccdc438d7
   106 static ChunkIndex next_chunk_index(ChunkIndex i) {
   106 static ChunkIndex next_chunk_index(ChunkIndex i) {
   107   assert(i < NumberOfInUseLists, "Out of bound");
   107   assert(i < NumberOfInUseLists, "Out of bound");
   108   return (ChunkIndex) (i+1);
   108   return (ChunkIndex) (i+1);
   109 }
   109 }
   110 
   110 
       
   111 static const char* scale_unit(size_t scale) {
       
   112   switch(scale) {
       
   113     case 1: return "BYTES";
       
   114     case K: return "KB";
       
   115     case M: return "MB";
       
   116     case G: return "GB";
       
   117     default:
       
   118       ShouldNotReachHere();
       
   119       return NULL;
       
   120   }
       
   121 }
       
   122 
   111 volatile intptr_t MetaspaceGC::_capacity_until_GC = 0;
   123 volatile intptr_t MetaspaceGC::_capacity_until_GC = 0;
   112 uint MetaspaceGC::_shrink_factor = 0;
   124 uint MetaspaceGC::_shrink_factor = 0;
   113 bool MetaspaceGC::_should_concurrent_collect = false;
   125 bool MetaspaceGC::_should_concurrent_collect = false;
   114 
   126 
   115 typedef class FreeList<Metachunk> ChunkList;
   127 typedef class FreeList<Metachunk> ChunkList;
   174     size_t total_size_humongous_chunks;
   186     size_t total_size_humongous_chunks;
   175   };
   187   };
   176 
   188 
   177   void locked_get_statistics(ChunkManagerStatistics* stat) const;
   189   void locked_get_statistics(ChunkManagerStatistics* stat) const;
   178   void get_statistics(ChunkManagerStatistics* stat) const;
   190   void get_statistics(ChunkManagerStatistics* stat) const;
   179   static void print_statistics(const ChunkManagerStatistics* stat, outputStream* out);
   191   static void print_statistics(const ChunkManagerStatistics* stat, outputStream* out, size_t scale);
   180 
   192 
   181  public:
   193  public:
   182 
   194 
   183   ChunkManager(size_t specialized_size, size_t small_size, size_t medium_size)
   195   ChunkManager(size_t specialized_size, size_t small_size, size_t medium_size)
   184       : _free_chunks_total(0), _free_chunks_count(0) {
   196       : _free_chunks_total(0), _free_chunks_count(0) {
   281 
   293 
   282   void print_on(outputStream* st) const;
   294   void print_on(outputStream* st) const;
   283 
   295 
   284   // Prints composition for both non-class and (if available)
   296   // Prints composition for both non-class and (if available)
   285   // class chunk manager.
   297   // class chunk manager.
   286   static void print_all_chunkmanagers(outputStream* out);
   298   static void print_all_chunkmanagers(outputStream* out, size_t scale = 1);
   287 };
   299 };
   288 
   300 
   289 class SmallBlocks : public CHeapObj<mtClass> {
   301 class SmallBlocks : public CHeapObj<mtClass> {
   290   const static uint _small_block_max_size = sizeof(TreeChunk<Metablock,  FreeList<Metablock> >)/HeapWordSize;
   302   const static uint _small_block_max_size = sizeof(TreeChunk<Metablock,  FreeList<Metablock> >)/HeapWordSize;
   291   const static uint _small_block_min_size = sizeof(Metablock)/HeapWordSize;
   303   const static uint _small_block_min_size = sizeof(Metablock)/HeapWordSize;
  1722   return false;
  1734   return false;
  1723 }
  1735 }
  1724 #endif
  1736 #endif
  1725 
  1737 
  1726 // ChunkManager methods
  1738 // ChunkManager methods
  1727 
       
  1728 size_t ChunkManager::free_chunks_total_words() {
  1739 size_t ChunkManager::free_chunks_total_words() {
  1729   return _free_chunks_total;
  1740   return _free_chunks_total;
  1730 }
  1741 }
  1731 
  1742 
  1732 size_t ChunkManager::free_chunks_total_bytes() {
  1743 size_t ChunkManager::free_chunks_total_bytes() {
  2055   MutexLockerEx cl(SpaceManager::expand_lock(),
  2066   MutexLockerEx cl(SpaceManager::expand_lock(),
  2056                    Mutex::_no_safepoint_check_flag);
  2067                    Mutex::_no_safepoint_check_flag);
  2057   locked_get_statistics(stat);
  2068   locked_get_statistics(stat);
  2058 }
  2069 }
  2059 
  2070 
  2060 void ChunkManager::print_statistics(const ChunkManagerStatistics* stat, outputStream* out) {
  2071 void ChunkManager::print_statistics(const ChunkManagerStatistics* stat, outputStream* out, size_t scale) {
  2061   size_t total = 0;
  2072   size_t total = 0;
       
  2073   assert(scale == 1 || scale == K || scale == M || scale == G, "Invalid scale");
       
  2074 
       
  2075   const char* unit = scale_unit(scale);
  2062   for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
  2076   for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
  2063     out->print_cr("  " SIZE_FORMAT " %s (" SIZE_FORMAT " bytes) chunks, total " SIZE_FORMAT " bytes",
  2077     out->print("  " SIZE_FORMAT " %s (" SIZE_FORMAT " bytes) chunks, total ",
  2064                  stat->num_by_type[i], chunk_size_name(i),
  2078                    stat->num_by_type[i], chunk_size_name(i),
  2065                  stat->single_size_by_type[i],
  2079                    stat->single_size_by_type[i]);
  2066                  stat->total_size_by_type[i]);
  2080     if (scale == 1) {
       
  2081       out->print_cr(SIZE_FORMAT " bytes", stat->total_size_by_type[i]);
       
  2082     } else {
       
  2083       out->print_cr("%.2f%s", (float)stat->total_size_by_type[i] / scale, unit);
       
  2084     }
       
  2085 
  2067     total += stat->total_size_by_type[i];
  2086     total += stat->total_size_by_type[i];
  2068   }
  2087   }
  2069   out->print_cr("  " SIZE_FORMAT " humongous chunks, total " SIZE_FORMAT " bytes",
  2088 
  2070                stat->num_humongous_chunks, stat->total_size_humongous_chunks);
  2089 
  2071   total += stat->total_size_humongous_chunks;
  2090   total += stat->total_size_humongous_chunks;
  2072   out->print_cr("  total size: " SIZE_FORMAT ".", total);
  2091 
  2073 }
  2092   if (scale == 1) {
  2074 
  2093     out->print_cr("  " SIZE_FORMAT " humongous chunks, total " SIZE_FORMAT " bytes",
  2075 void ChunkManager::print_all_chunkmanagers(outputStream* out) {
  2094     stat->num_humongous_chunks, stat->total_size_humongous_chunks);
       
  2095 
       
  2096     out->print_cr("  total size: " SIZE_FORMAT " bytes.", total);
       
  2097   } else {
       
  2098     out->print_cr("  " SIZE_FORMAT " humongous chunks, total %.2f%s",
       
  2099     stat->num_humongous_chunks,
       
  2100     (float)stat->total_size_humongous_chunks / scale, unit);
       
  2101 
       
  2102     out->print_cr("  total size: %.2f%s.", (float)total / scale, unit);
       
  2103   }
       
  2104 
       
  2105 }
       
  2106 
       
  2107 void ChunkManager::print_all_chunkmanagers(outputStream* out, size_t scale) {
       
  2108   assert(scale == 1 || scale == K || scale == M || scale == G, "Invalid scale");
       
  2109 
  2076   // Note: keep lock protection only to retrieving statistics; keep printing
  2110   // Note: keep lock protection only to retrieving statistics; keep printing
  2077   // out of lock protection
  2111   // out of lock protection
  2078   ChunkManagerStatistics stat;
  2112   ChunkManagerStatistics stat;
  2079   out->print_cr("Chunkmanager (non-class):");
  2113   out->print_cr("Chunkmanager (non-class):");
  2080   const ChunkManager* const non_class_cm = Metaspace::chunk_manager_metadata();
  2114   const ChunkManager* const non_class_cm = Metaspace::chunk_manager_metadata();
  2081   if (non_class_cm != NULL) {
  2115   if (non_class_cm != NULL) {
  2082     non_class_cm->get_statistics(&stat);
  2116     non_class_cm->get_statistics(&stat);
  2083     ChunkManager::print_statistics(&stat, out);
  2117     ChunkManager::print_statistics(&stat, out, scale);
  2084   } else {
  2118   } else {
  2085     out->print_cr("unavailable.");
  2119     out->print_cr("unavailable.");
  2086   }
  2120   }
  2087   out->print_cr("Chunkmanager (class):");
  2121   out->print_cr("Chunkmanager (class):");
  2088   const ChunkManager* const class_cm = Metaspace::chunk_manager_class();
  2122   const ChunkManager* const class_cm = Metaspace::chunk_manager_class();
  2089   if (class_cm != NULL) {
  2123   if (class_cm != NULL) {
  2090     class_cm->get_statistics(&stat);
  2124     class_cm->get_statistics(&stat);
  2091     ChunkManager::print_statistics(&stat, out);
  2125     ChunkManager::print_statistics(&stat, out, scale);
  2092   } else {
  2126   } else {
  2093     out->print_cr("unavailable.");
  2127     out->print_cr("unavailable.");
  2094   }
  2128   }
  2095 }
  2129 }
  2096 
  2130 
  2978              small_waste, medium_count, medium_waste, humongous_count);
  3012              small_waste, medium_count, medium_waste, humongous_count);
  2979   if (Metaspace::using_class_space()) {
  3013   if (Metaspace::using_class_space()) {
  2980     print_class_waste(out);
  3014     print_class_waste(out);
  2981   }
  3015   }
  2982 }
  3016 }
       
  3017 
       
  3018 class MetadataStats VALUE_OBJ_CLASS_SPEC {
       
  3019 private:
       
  3020   size_t _capacity;
       
  3021   size_t _used;
       
  3022   size_t _free;
       
  3023   size_t _waste;
       
  3024 
       
  3025 public:
       
  3026   MetadataStats() : _capacity(0), _used(0), _free(0), _waste(0) { }
       
  3027   MetadataStats(size_t capacity, size_t used, size_t free, size_t waste)
       
  3028   : _capacity(capacity), _used(used), _free(free), _waste(waste) { }
       
  3029 
       
  3030   void add(const MetadataStats& stats) {
       
  3031     _capacity += stats.capacity();
       
  3032     _used += stats.used();
       
  3033     _free += stats.free();
       
  3034     _waste += stats.waste();
       
  3035   }
       
  3036 
       
  3037   size_t capacity() const { return _capacity; }
       
  3038   size_t used() const     { return _used; }
       
  3039   size_t free() const     { return _free; }
       
  3040   size_t waste() const    { return _waste; }
       
  3041 
       
  3042   void print_on(outputStream* out, size_t scale) const;
       
  3043 };
       
  3044 
       
  3045 
       
  3046 void MetadataStats::print_on(outputStream* out, size_t scale) const {
       
  3047   const char* unit = scale_unit(scale);
       
  3048   out->print_cr("capacity=%10.2f%s used=%10.2f%s free=%10.2f%s waste=%10.2f%s",
       
  3049     (float)capacity() / scale, unit,
       
  3050     (float)used() / scale, unit,
       
  3051     (float)free() / scale, unit,
       
  3052     (float)waste() / scale, unit);
       
  3053 }
       
  3054 
       
  3055 class PrintCLDMetaspaceInfoClosure : public CLDClosure {
       
  3056 private:
       
  3057   outputStream*  _out;
       
  3058   size_t         _scale;
       
  3059 
       
  3060   size_t         _total_count;
       
  3061   MetadataStats  _total_metadata;
       
  3062   MetadataStats  _total_class;
       
  3063 
       
  3064   size_t         _total_anon_count;
       
  3065   MetadataStats  _total_anon_metadata;
       
  3066   MetadataStats  _total_anon_class;
       
  3067 
       
  3068 public:
       
  3069   PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale = K)
       
  3070   : _out(out), _scale(scale), _total_count(0), _total_anon_count(0) { }
       
  3071 
       
  3072   ~PrintCLDMetaspaceInfoClosure() {
       
  3073     print_summary();
       
  3074   }
       
  3075 
       
  3076   void do_cld(ClassLoaderData* cld) {
       
  3077     assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
       
  3078 
       
  3079     if (cld->is_unloading()) return;
       
  3080     Metaspace* msp = cld->metaspace_or_null();
       
  3081     if (msp == NULL) {
       
  3082       return;
       
  3083     }
       
  3084 
       
  3085     bool anonymous = false;
       
  3086     if (cld->is_anonymous()) {
       
  3087       _out->print_cr("ClassLoader: for anonymous class");
       
  3088       anonymous = true;
       
  3089     } else {
       
  3090       ResourceMark rm;
       
  3091       _out->print_cr("ClassLoader: %s", cld->loader_name());
       
  3092     }
       
  3093 
       
  3094     print_metaspace(msp, anonymous);
       
  3095     _out->cr();
       
  3096   }
       
  3097 
       
  3098 private:
       
  3099   void print_metaspace(Metaspace* msp, bool anonymous);
       
  3100   void print_summary() const;
       
  3101 };
       
  3102 
       
  3103 void PrintCLDMetaspaceInfoClosure::print_metaspace(Metaspace* msp, bool anonymous){
       
  3104   assert(msp != NULL, "Sanity");
       
  3105   SpaceManager* vsm = msp->vsm();
       
  3106   const char* unit = scale_unit(_scale);
       
  3107 
       
  3108   size_t capacity = vsm->sum_capacity_in_chunks_in_use() * BytesPerWord;
       
  3109   size_t used = vsm->sum_used_in_chunks_in_use() * BytesPerWord;
       
  3110   size_t free = vsm->sum_free_in_chunks_in_use() * BytesPerWord;
       
  3111   size_t waste = vsm->sum_waste_in_chunks_in_use() * BytesPerWord;
       
  3112 
       
  3113   _total_count ++;
       
  3114   MetadataStats metadata_stats(capacity, used, free, waste);
       
  3115   _total_metadata.add(metadata_stats);
       
  3116 
       
  3117   if (anonymous) {
       
  3118     _total_anon_count ++;
       
  3119     _total_anon_metadata.add(metadata_stats);
       
  3120   }
       
  3121 
       
  3122   _out->print("  Metadata   ");
       
  3123   metadata_stats.print_on(_out, _scale);
       
  3124 
       
  3125   if (Metaspace::using_class_space()) {
       
  3126     vsm = msp->class_vsm();
       
  3127 
       
  3128     capacity = vsm->sum_capacity_in_chunks_in_use() * BytesPerWord;
       
  3129     used = vsm->sum_used_in_chunks_in_use() * BytesPerWord;
       
  3130     free = vsm->sum_free_in_chunks_in_use() * BytesPerWord;
       
  3131     waste = vsm->sum_waste_in_chunks_in_use() * BytesPerWord;
       
  3132 
       
  3133     MetadataStats class_stats(capacity, used, free, waste);
       
  3134     _total_class.add(class_stats);
       
  3135 
       
  3136     if (anonymous) {
       
  3137       _total_anon_class.add(class_stats);
       
  3138     }
       
  3139 
       
  3140     _out->print("  Class data ");
       
  3141     class_stats.print_on(_out, _scale);
       
  3142   }
       
  3143 }
       
  3144 
       
  3145 void PrintCLDMetaspaceInfoClosure::print_summary() const {
       
  3146   const char* unit = scale_unit(_scale);
       
  3147   _out->cr();
       
  3148   _out->print_cr("Summary:");
       
  3149 
       
  3150   MetadataStats total;
       
  3151   total.add(_total_metadata);
       
  3152   total.add(_total_class);
       
  3153 
       
  3154   _out->print("  Total class loaders=" SIZE_FORMAT_W(6) " ", _total_count);
       
  3155   total.print_on(_out, _scale);
       
  3156 
       
  3157   _out->print("                    Metadata ");
       
  3158   _total_metadata.print_on(_out, _scale);
       
  3159 
       
  3160   if (Metaspace::using_class_space()) {
       
  3161     _out->print("                  Class data ");
       
  3162     _total_class.print_on(_out, _scale);
       
  3163   }
       
  3164   _out->cr();
       
  3165 
       
  3166   MetadataStats total_anon;
       
  3167   total_anon.add(_total_anon_metadata);
       
  3168   total_anon.add(_total_anon_class);
       
  3169 
       
  3170   _out->print("For anonymous classes=" SIZE_FORMAT_W(6) " ", _total_anon_count);
       
  3171   total_anon.print_on(_out, _scale);
       
  3172 
       
  3173   _out->print("                    Metadata ");
       
  3174   _total_anon_metadata.print_on(_out, _scale);
       
  3175 
       
  3176   if (Metaspace::using_class_space()) {
       
  3177     _out->print("                  Class data ");
       
  3178     _total_anon_class.print_on(_out, _scale);
       
  3179   }
       
  3180 }
       
  3181 
       
  3182 void MetaspaceAux::print_metadata_for_nmt(outputStream* out, size_t scale) {
       
  3183   const char* unit = scale_unit(scale);
       
  3184   out->print_cr("Metaspaces:");
       
  3185   out->print_cr("  Metadata space: reserved=" SIZE_FORMAT_W(10) "%s committed=" SIZE_FORMAT_W(10) "%s",
       
  3186     reserved_bytes(Metaspace::NonClassType) / scale, unit,
       
  3187     committed_bytes(Metaspace::NonClassType) / scale, unit);
       
  3188   if (Metaspace::using_class_space()) {
       
  3189     out->print_cr("  Class    space: reserved=" SIZE_FORMAT_W(10) "%s committed=" SIZE_FORMAT_W(10) "%s",
       
  3190     reserved_bytes(Metaspace::ClassType) / scale, unit,
       
  3191     committed_bytes(Metaspace::ClassType) / scale, unit);
       
  3192   }
       
  3193 
       
  3194   out->cr();
       
  3195   ChunkManager::print_all_chunkmanagers(out, scale);
       
  3196 
       
  3197   out->cr();
       
  3198   out->print_cr("Per-classloader metadata:");
       
  3199   out->cr();
       
  3200 
       
  3201   PrintCLDMetaspaceInfoClosure cl(out, scale);
       
  3202   ClassLoaderDataGraph::cld_do(&cl);
       
  3203 }
       
  3204 
  2983 
  3205 
  2984 // Dump global metaspace things from the end of ClassLoaderDataGraph
  3206 // Dump global metaspace things from the end of ClassLoaderDataGraph
  2985 void MetaspaceAux::dump(outputStream* out) {
  3207 void MetaspaceAux::dump(outputStream* out) {
  2986   out->print_cr("All Metaspace:");
  3208   out->print_cr("All Metaspace:");
  2987   out->print("data space: "); print_on(out, Metaspace::NonClassType);
  3209   out->print("data space: "); print_on(out, Metaspace::NonClassType);