1 /*
   2  * Copyright (c) 2003, 2011, 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("PermSize         = ", getFlagValue("PermSize", flagMap));
  69       printValMB("MaxPermSize      = ", getFlagValue("MaxPermSize", flagMap));
  70 
  71       System.out.println();
  72       System.out.println("Heap Usage:");
  73 
  74       if (heap instanceof SharedHeap) {
  75          SharedHeap sharedHeap = (SharedHeap) heap;
  76          if (sharedHeap instanceof GenCollectedHeap) {
  77             GenCollectedHeap genHeap = (GenCollectedHeap) sharedHeap;
  78             for (int n = 0; n < genHeap.nGens(); n++) {
  79                Generation gen = genHeap.getGen(n);
  80                if (gen instanceof sun.jvm.hotspot.memory.DefNewGeneration) {
  81                   System.out.println("New Generation (Eden + 1 Survivor Space):");
  82                   printGen(gen);
  83 
  84                   ContiguousSpace eden = ((DefNewGeneration)gen).eden();
  85                   System.out.println("Eden Space:");
  86                   printSpace(eden);
  87 
  88                   ContiguousSpace from = ((DefNewGeneration)gen).from();
  89                   System.out.println("From Space:");
  90                   printSpace(from);
  91 
  92                   ContiguousSpace to = ((DefNewGeneration)gen).to();
  93                   System.out.println("To Space:");
  94                   printSpace(to);
  95                } else {
  96                   System.out.println(gen.name() + ":");
  97                   printGen(gen);
  98                }
  99             }
 100          } else if (sharedHeap instanceof G1CollectedHeap) {
 101              G1CollectedHeap g1h = (G1CollectedHeap) sharedHeap;
 102              G1MonitoringSupport g1mm = g1h.g1mm();
 103              System.out.println("G1 Young Generation");
 104              printG1Space("Eden Space:", g1mm.edenUsed(), g1mm.edenCommitted());
 105              printG1Space("From Space:", g1mm.survivorUsed(), g1mm.survivorCommitted());
 106              printG1Space("To Space:", 0, 0);
 107              printG1Space("G1 Old Generation", g1mm.oldUsed(), g1mm.oldCommitted());
 108          } else {
 109              throw new RuntimeException("unknown SharedHeap type : " + heap.getClass());
 110          }
 111          // Perm generation shared by the above
 112          Generation permGen = sharedHeap.permGen();
 113          System.out.println("Perm Generation:");
 114          printGen(permGen);
 115       } else if (heap instanceof ParallelScavengeHeap) {
 116          ParallelScavengeHeap psh = (ParallelScavengeHeap) heap;
 117          PSYoungGen youngGen = psh.youngGen();
 118          printPSYoungGen(youngGen);
 119 
 120          PSOldGen oldGen = psh.oldGen();
 121          long oldFree = oldGen.capacity() - oldGen.used();
 122          System.out.println("PS Old Generation");
 123          printValMB("capacity = ", oldGen.capacity());
 124          printValMB("used     = ", oldGen.used());
 125          printValMB("free     = ", oldFree);
 126          System.out.println(alignment + (double)oldGen.used() * 100.0 / oldGen.capacity() + "% used");
 127 
 128          PSPermGen permGen = psh.permGen();
 129          long permFree = permGen.capacity() - permGen.used();
 130          System.out.println("PS Perm Generation");
 131          printValMB("capacity = ", permGen.capacity());
 132          printValMB("used     = ", permGen.used());
 133          printValMB("free     = ", permFree);
 134          System.out.println(alignment + (double)permGen.used() * 100.0 / permGen.capacity() + "% used");
 135       } else {
 136          throw new RuntimeException("unknown CollectedHeap type : " + heap.getClass());
 137       }
 138 
 139       System.out.println();
 140       printInternStringStatistics();
 141    }
 142 
 143    // Helper methods
 144 
 145    private void printGCAlgorithm(Map flagMap) {
 146        // print about new generation
 147        long l = getFlagValue("UseParNewGC", flagMap);
 148        if (l == 1L) {
 149           System.out.println("using parallel threads in the new generation.");
 150        }
 151 
 152        l = getFlagValue("UseTLAB", flagMap);
 153        if (l == 1L) {
 154           System.out.println("using thread-local object allocation.");
 155        }
 156 
 157        l = getFlagValue("UseConcMarkSweepGC", flagMap);
 158        if (l == 1L) {
 159           System.out.println("Concurrent Mark-Sweep GC");
 160           return;
 161        }
 162 
 163        l = getFlagValue("UseParallelGC", flagMap);
 164        if (l == 1L) {
 165           System.out.print("Parallel GC ");
 166           l = getFlagValue("ParallelGCThreads", flagMap);
 167           System.out.println("with " + l + " thread(s)");
 168           return;
 169        }
 170 
 171        l = getFlagValue("UseG1GC", flagMap);
 172        if (l == 1L) {
 173            System.out.print("Garbage-First (G1) GC ");
 174            l = getFlagValue("ParallelGCThreads", flagMap);
 175            System.out.println("with " + l + " thread(s)");
 176            return;
 177        }
 178 
 179        System.out.println("Mark Sweep Compact GC");
 180    }
 181 
 182    private void printPSYoungGen(PSYoungGen youngGen) {
 183       System.out.println("PS Young Generation");
 184       MutableSpace eden = youngGen.edenSpace();
 185       System.out.println("Eden Space:");
 186       printMutableSpace(eden);
 187       MutableSpace from = youngGen.fromSpace();
 188       System.out.println("From Space:");
 189       printMutableSpace(from);
 190       MutableSpace to = youngGen.toSpace();
 191       System.out.println("To Space:");
 192       printMutableSpace(to);
 193    }
 194 
 195    private void printMutableSpace(MutableSpace space) {
 196       printValMB("capacity = ", space.capacity());
 197       printValMB("used     = ", space.used());
 198       long free = space.capacity() - space.used();
 199       printValMB("free     = ", free);
 200       System.out.println(alignment + (double)space.used() * 100.0 / space.capacity() + "% used");
 201    }
 202 
 203    private static String alignment = "   ";
 204 
 205    private void printGen(Generation gen) {
 206       printValMB("capacity = ", gen.capacity());
 207       printValMB("used     = ", gen.used());
 208       printValMB("free     = ", gen.free());
 209       System.out.println(alignment + (double)gen.used() * 100.0 / gen.capacity() + "% used");
 210    }
 211 
 212    private void printSpace(ContiguousSpace space) {
 213       printValMB("capacity = ", space.capacity());
 214       printValMB("used     = ", space.used());
 215       printValMB("free     = ", space.free());
 216       System.out.println(alignment +  (double)space.used() * 100.0 / space.capacity() + "% used");
 217    }
 218 
 219    private void printG1Space(String spaceName, long used, long capacity) {
 220       long free = capacity - used;
 221       System.out.println(spaceName);
 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 }