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