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