1 /*
   2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.tools;
  26 
  27 import java.util.*;
  28 import sun.jvm.hotspot.gc_interface.*;
  29 import sun.jvm.hotspot.gc_implementation.g1.*;
  30 import sun.jvm.hotspot.gc_implementation.shenandoah.*;
  31 import sun.jvm.hotspot.gc_implementation.parallelScavenge.*;
  32 import sun.jvm.hotspot.gc_implementation.shared.*;
  33 import sun.jvm.hotspot.debugger.JVMDebugger;
  34 import sun.jvm.hotspot.memory.*;
  35 import sun.jvm.hotspot.oops.*;
  36 import sun.jvm.hotspot.runtime.*;
  37 
  38 public class HeapSummary extends Tool {
  39 
  40    public HeapSummary() {
  41       super();
  42    }
  43 
  44    public HeapSummary(JVMDebugger d) {
  45       super(d);
  46    }
  47 
  48    public static void main(String[] args) {
  49       HeapSummary hs = new HeapSummary();
  50       hs.execute(args);
  51    }
  52 
  53    public void run() {
  54       CollectedHeap heap = VM.getVM().getUniverse().heap();
  55       VM.Flag[] flags = VM.getVM().getCommandLineFlags();
  56       Map flagMap = new HashMap();
  57       if (flags == null) {
  58          System.out.println("WARNING: command line flags are not available");
  59       } else {
  60          for (int f = 0; f < flags.length; f++) {
  61             flagMap.put(flags[f].getName(), flags[f]);
  62          }
  63       }
  64 
  65       System.out.println();
  66       printGCAlgorithm(flagMap);
  67       System.out.println();
  68       System.out.println("Heap Configuration:");
  69       printValue("MinHeapFreeRatio         = ", getFlagValue("MinHeapFreeRatio", flagMap));
  70       printValue("MaxHeapFreeRatio         = ", getFlagValue("MaxHeapFreeRatio", flagMap));
  71       printValMB("MaxHeapSize              = ", getFlagValue("MaxHeapSize", flagMap));
  72       printValMB("NewSize                  = ", getFlagValue("NewSize", flagMap));
  73       printValMB("MaxNewSize               = ", getFlagValue("MaxNewSize", flagMap));
  74       printValMB("OldSize                  = ", getFlagValue("OldSize", flagMap));
  75       printValue("NewRatio                 = ", getFlagValue("NewRatio", flagMap));
  76       printValue("SurvivorRatio            = ", getFlagValue("SurvivorRatio", flagMap));
  77       printValMB("MetaspaceSize            = ", getFlagValue("MetaspaceSize", flagMap));
  78       printValMB("CompressedClassSpaceSize = ", getFlagValue("CompressedClassSpaceSize", flagMap));
  79       printValMB("MaxMetaspaceSize         = ", getFlagValue("MaxMetaspaceSize", flagMap));
  80       if (heap instanceof ShenandoahHeap) {
  81          printValMB("ShenandoahRegionSize     = ", ShenandoahHeapRegion.regionSizeBytes());
  82       } else {
  83          printValMB("G1HeapRegionSize         = ", HeapRegion.grainBytes());
  84       }
  85 
  86       System.out.println();
  87       System.out.println("Heap Usage:");
  88 
  89       if (heap instanceof SharedHeap) {
  90          SharedHeap sharedHeap = (SharedHeap) heap;
  91          if (sharedHeap instanceof GenCollectedHeap) {
  92             GenCollectedHeap genHeap = (GenCollectedHeap) sharedHeap;
  93             for (int n = 0; n < genHeap.nGens(); n++) {
  94                Generation gen = genHeap.getGen(n);
  95                if (gen instanceof sun.jvm.hotspot.memory.DefNewGeneration) {
  96                   System.out.println("New Generation (Eden + 1 Survivor Space):");
  97                   printGen(gen);
  98 
  99                   ContiguousSpace eden = ((DefNewGeneration)gen).eden();
 100                   System.out.println("Eden Space:");
 101                   printSpace(eden);
 102 
 103                   ContiguousSpace from = ((DefNewGeneration)gen).from();
 104                   System.out.println("From Space:");
 105                   printSpace(from);
 106 
 107                   ContiguousSpace to = ((DefNewGeneration)gen).to();
 108                   System.out.println("To Space:");
 109                   printSpace(to);
 110                } else {
 111                   System.out.println(gen.name() + ":");
 112                   printGen(gen);
 113                }
 114             }
 115          } else if (sharedHeap instanceof G1CollectedHeap) {
 116              G1CollectedHeap g1h = (G1CollectedHeap) sharedHeap;
 117              G1MonitoringSupport g1mm = g1h.g1mm();
 118              long edenRegionNum = g1mm.edenRegionNum();
 119              long survivorRegionNum = g1mm.survivorRegionNum();
 120              HeapRegionSetBase oldSet = g1h.oldSet();
 121              HeapRegionSetBase humongousSet = g1h.humongousSet();
 122              long oldRegionNum = oldSet.count().length()
 123                           + humongousSet.count().capacity() / HeapRegion.grainBytes();
 124              printG1Space("G1 Heap:", g1h.n_regions(),
 125                           g1h.used(), g1h.capacity());
 126              System.out.println("G1 Young Generation:");
 127              printG1Space("Eden Space:", edenRegionNum,
 128                           g1mm.edenUsed(), g1mm.edenCommitted());
 129              printG1Space("Survivor Space:", survivorRegionNum,
 130                           g1mm.survivorUsed(), g1mm.survivorCommitted());
 131              printG1Space("G1 Old Generation:", oldRegionNum,
 132                           g1mm.oldUsed(), g1mm.oldCommitted());
 133          } else {
 134              throw new RuntimeException("unknown SharedHeap type : " + heap.getClass());
 135          }
 136       } else if (heap instanceof ParallelScavengeHeap) {
 137          ParallelScavengeHeap psh = (ParallelScavengeHeap) heap;
 138          PSYoungGen youngGen = psh.youngGen();
 139          printPSYoungGen(youngGen);
 140 
 141          PSOldGen oldGen = psh.oldGen();
 142          long oldFree = oldGen.capacity() - oldGen.used();
 143          System.out.println("PS Old Generation");
 144          printValMB("capacity = ", oldGen.capacity());
 145          printValMB("used     = ", oldGen.used());
 146          printValMB("free     = ", oldFree);
 147          System.out.println(alignment + (double)oldGen.used() * 100.0 / oldGen.capacity() + "% used");
 148       } else if (heap instanceof ShenandoahHeap) {
 149          ShenandoahHeap sh = (ShenandoahHeap) heap;
 150          long num_regions = sh.numOfRegions();
 151          System.out.println("Shenandoah Heap:");
 152          System.out.println("   regions   = " + num_regions);
 153          printValMB("capacity  = ", num_regions * ShenandoahHeapRegion.regionSizeBytes());
 154          printValMB("used      = ", sh.used());
 155          printValMB("committed = ", sh.committed());
 156       } else {
 157          throw new RuntimeException("unknown CollectedHeap type : " + heap.getClass());
 158       }
 159 
 160       System.out.println();
 161       printInternStringStatistics();
 162    }
 163 
 164    // Helper methods
 165 
 166    private void printGCAlgorithm(Map flagMap) {
 167        // print about new generation
 168        long l = getFlagValue("UseParNewGC", flagMap);
 169        if (l == 1L) {
 170           System.out.println("using parallel threads in the new generation.");
 171        }
 172 
 173        l = getFlagValue("UseTLAB", flagMap);
 174        if (l == 1L) {
 175           System.out.println("using thread-local object allocation.");
 176        }
 177 
 178        l = getFlagValue("UseConcMarkSweepGC", flagMap);
 179        if (l == 1L) {
 180           System.out.println("Concurrent Mark-Sweep GC");
 181           return;
 182        }
 183 
 184        l = getFlagValue("UseParallelGC", flagMap);
 185        if (l == 1L) {
 186           System.out.print("Parallel GC ");
 187           l = getFlagValue("ParallelGCThreads", flagMap);
 188           System.out.println("with " + l + " thread(s)");
 189           return;
 190        }
 191 
 192        l = getFlagValue("UseG1GC", flagMap);
 193        if (l == 1L) {
 194            System.out.print("Garbage-First (G1) GC ");
 195            l = getFlagValue("ParallelGCThreads", flagMap);
 196            System.out.println("with " + l + " thread(s)");
 197            return;
 198        }
 199 
 200        l = getFlagValue("UseShenandoahGC", flagMap);
 201        if (l == 1L) {
 202            System.out.print("Shenandoah GC ");
 203            l = getFlagValue("ParallelGCThreads", flagMap);
 204            System.out.println("with " + l + " thread(s)");
 205            return;
 206        }
 207 
 208        System.out.println("Mark Sweep Compact GC");
 209    }
 210 
 211    private void printPSYoungGen(PSYoungGen youngGen) {
 212       System.out.println("PS Young Generation");
 213       MutableSpace eden = youngGen.edenSpace();
 214       System.out.println("Eden Space:");
 215       printMutableSpace(eden);
 216       MutableSpace from = youngGen.fromSpace();
 217       System.out.println("From Space:");
 218       printMutableSpace(from);
 219       MutableSpace to = youngGen.toSpace();
 220       System.out.println("To Space:");
 221       printMutableSpace(to);
 222    }
 223 
 224    private void printMutableSpace(MutableSpace space) {
 225       printValMB("capacity = ", space.capacity());
 226       printValMB("used     = ", space.used());
 227       long free = space.capacity() - space.used();
 228       printValMB("free     = ", free);
 229       System.out.println(alignment + (double)space.used() * 100.0 / space.capacity() + "% used");
 230    }
 231 
 232    private static String alignment = "   ";
 233 
 234    private void printGen(Generation gen) {
 235       printValMB("capacity = ", gen.capacity());
 236       printValMB("used     = ", gen.used());
 237       printValMB("free     = ", gen.free());
 238       System.out.println(alignment + (double)gen.used() * 100.0 / gen.capacity() + "% used");
 239    }
 240 
 241    private void printSpace(ContiguousSpace space) {
 242       printValMB("capacity = ", space.capacity());
 243       printValMB("used     = ", space.used());
 244       printValMB("free     = ", space.free());
 245       System.out.println(alignment +  (double)space.used() * 100.0 / space.capacity() + "% used");
 246    }
 247 
 248    private void printG1Space(String spaceName, long regionNum,
 249                              long used, long capacity) {
 250       long free = capacity - used;
 251       System.out.println(spaceName);
 252       printValue("regions  = ", regionNum);
 253       printValMB("capacity = ", capacity);
 254       printValMB("used     = ", used);
 255       printValMB("free     = ", free);
 256       double occPerc = (capacity > 0) ? (double) used * 100.0 / capacity : 0.0;
 257       System.out.println(alignment + occPerc + "% used");
 258    }
 259 
 260    private static final double FACTOR = 1024*1024;
 261    private void printValMB(String title, long value) {
 262       if (value < 0) {
 263         System.out.println(alignment + title +   (value >>> 20)  + " MB");
 264       } else {
 265         double mb = value/FACTOR;
 266         System.out.println(alignment + title + value + " (" + mb + "MB)");
 267       }
 268    }
 269 
 270    private void printValue(String title, long value) {
 271       System.out.println(alignment + title + value);
 272    }
 273 
 274    private long getFlagValue(String name, Map flagMap) {
 275       VM.Flag f = (VM.Flag) flagMap.get(name);
 276       if (f != null) {
 277          if (f.isBool()) {
 278             return f.getBool()? 1L : 0L;
 279          } else {
 280             return Long.parseLong(f.getValue());
 281          }
 282       } else {
 283          return -1;
 284       }
 285    }
 286 
 287    private void printInternStringStatistics() {
 288       class StringStat implements StringTable.StringVisitor {
 289          private int count;
 290          private long size;
 291          private OopField stringValueField;
 292 
 293          StringStat() {
 294             VM vm = VM.getVM();
 295             SystemDictionary sysDict = vm.getSystemDictionary();
 296             InstanceKlass strKlass = sysDict.getStringKlass();
 297             // String has a field named 'value' of type 'char[]'.
 298             stringValueField = (OopField) strKlass.findField("value", "[C");
 299          }
 300 
 301          private long stringSize(Instance instance) {
 302             // We include String content in size calculation.
 303             return instance.getObjectSize() +
 304                    stringValueField.getValue(instance).getObjectSize();
 305          }
 306 
 307          public void visit(Instance str) {
 308             count++;
 309             size += stringSize(str);
 310          }
 311 
 312          public void print() {
 313             System.out.println(count +
 314                   " interned Strings occupying " + size + " bytes.");
 315          }
 316       }
 317 
 318       StringStat stat = new StringStat();
 319       StringTable strTable = VM.getVM().getStringTable();
 320       strTable.stringsDo(stat);
 321       stat.print();
 322    }
 323 }