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