Coverage Report - sk.baka.webvm.misc.MgmtUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
MgmtUtils
47%
38/80
38%
16/42
3.636
 
 1  
 /**
 2  
  * Copyright 2009 Martin Vysny.
 3  
  *
 4  
  * This file is part of WebVM.
 5  
  *
 6  
  * WebVM is free software: you can redistribute it and/or modify
 7  
  * it under the terms of the GNU General Public License as published by
 8  
  * the Free Software Foundation, either version 3 of the License, or
 9  
  * (at your option) any later version.
 10  
  *
 11  
  * WebVM is distributed in the hope that it will be useful,
 12  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  
  * GNU General Public License for more details.
 15  
  *
 16  
  * You should have received a copy of the GNU General Public License
 17  
  * along with WebVM.  If not, see <http://www.gnu.org/licenses/>.
 18  
  */
 19  
 package sk.baka.webvm.misc;
 20  
 
 21  
 import java.lang.management.ManagementFactory;
 22  
 import java.lang.management.MemoryPoolMXBean;
 23  
 import java.lang.management.MemoryType;
 24  
 import java.lang.management.MemoryUsage;
 25  
 import java.util.Collections;
 26  
 import java.util.List;
 27  
 import java.util.SortedMap;
 28  
 import java.util.TreeMap;
 29  
 import java.util.logging.Level;
 30  
 import java.util.logging.Logger;
 31  
 import static sk.baka.webvm.misc.Constants.*;
 32  
 
 33  
 /**
 34  
  * Provides utilities for the java.util.management package.
 35  
  * @author Martin Vysny
 36  
  */
 37  
 public final class MgmtUtils {
 38  
 
 39  1
     private static final Logger LOG = Logger.getLogger(MgmtUtils.class.getName());
 40  
 
 41  
     /**
 42  
      * Sums up all non-heap pools and return their memory usage.
 43  
      * @return memory usage, null if no pool collects non-heap space.
 44  
      */
 45  
     public static MemoryUsage getNonHeapSummary() {
 46  3
         MemoryUsage result = null;
 47  3
         final List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans();
 48  3
         for (final MemoryPoolMXBean bean : beans) {
 49  15
             if (bean.getType() != MemoryType.NON_HEAP) {
 50  9
                 continue;
 51  
             }
 52  6
             if (result == null) {
 53  3
                 result = bean.getUsage();
 54  
             } else {
 55  3
                 result = add(result, bean.getUsage());
 56  
             }
 57  
         }
 58  3
         return result;
 59  
     }
 60  
     private static final boolean IS_NON_HEAP;
 61  
 
 62  
     static {
 63  1
         boolean isNonHeap = false;
 64  
         try {
 65  1
             isNonHeap = getNonHeapSummary() != null;
 66  0
         } catch (Exception ex) {
 67  0
             LOG.log(Level.SEVERE, "Failed to get non-heap pools: " + ex, ex);
 68  1
         }
 69  1
         IS_NON_HEAP = isNonHeap;
 70  
     }
 71  
 
 72  
     /**
 73  
      * Checks if there is a non-heap pool in the memory pool list.
 74  
      * @return true if there is pool managing non-heap memory, false otherwise.
 75  
      */
 76  
     public static boolean isNonHeapPool() {
 77  0
         return IS_NON_HEAP;
 78  
     }
 79  
 
 80  0
     private MgmtUtils() {
 81  0
         throw new AssertionError();
 82  
     }
 83  
 
 84  
     /**
 85  
      * Computes and returns the memory usage object, using information only from {@link Runtime}.
 86  
      * @return non-null usage object.
 87  
      */
 88  
     public static MemoryUsage getHeapFromRuntime() {
 89  14
         long maxMem = Runtime.getRuntime().maxMemory();
 90  14
         long heapSize = Runtime.getRuntime().totalMemory();
 91  14
         long heapUsed = heapSize - Runtime.getRuntime().freeMemory();
 92  14
         return new MemoryUsage(-1, heapUsed, heapSize, maxMem == Long.MAX_VALUE ? -1 : maxMem);
 93  
     }
 94  
 
 95  
     /**
 96  
      * Sums two memory usages together. Does not allow null values.
 97  
      * @param u1 first usage, must not be null
 98  
      * @param u2 second usage, must not be null
 99  
      * @return a summed usage, never null
 100  
      */
 101  
     public static MemoryUsage add(final MemoryUsage u1, final MemoryUsage u2) {
 102  3
         return new MemoryUsage(addMem(u1.getInit(), u2.getInit()), u1.getUsed() + u2.getUsed(), u1.getCommitted() + u2.getCommitted(), addMem(u1.getMax(), u2.getMax()));
 103  
     }
 104  
 
 105  
     private static long addMem(final long l1, final long l2) {
 106  6
         if (l1 < 0 || l2 < 0) {
 107  0
             return -1;
 108  
         }
 109  6
         return l1 + l2;
 110  
     }
 111  
 
 112  
     /**
 113  
      * Returns a new object with all values divided by 1024*1024 (converted from bytes to mebibytes).
 114  
      * @param mu the memory usage to convert
 115  
      * @return new memory object with values in mebibytes. Returns null if null was supplied.
 116  
      */
 117  
     public static MemoryUsage getInMB(final MemoryUsage mu) {
 118  8
         if (mu == null) {
 119  0
             return null;
 120  
         }
 121  8
         return new MemoryUsage(mu.getInit() == -1 ? -1 : mu.getInit() / MEBIBYTES, mu.getUsed() / MEBIBYTES, mu.getCommitted() / MEBIBYTES, mu.getMax() == -1 ? -1 : mu.getMax() / MEBIBYTES);
 122  
     }
 123  
 
 124  
     /**
 125  
      * Formats a memory usage instance to a compact string. Uses the following format: [used (committed) / max].
 126  
      * @param mu the memory usage object.
 127  
      * @param inMegs if true then given memory usage values are already megabytes. If false then the values are in bytes.
 128  
      * @return [used (committed) / max], or [not available] if null was given
 129  
      */
 130  
     public static String toString(final MemoryUsage mu, final boolean inMegs) {
 131  0
         if (mu == null) {
 132  0
             return "[not available]";
 133  
         }
 134  0
         final StringBuilder sb = new StringBuilder();
 135  0
         sb.append('[');
 136  0
         sb.append(mu.getUsed());
 137  0
         if (inMegs) {
 138  0
             sb.append("M");
 139  
         }
 140  0
         sb.append(" (");
 141  0
         sb.append(mu.getCommitted());
 142  0
         if (inMegs) {
 143  0
             sb.append("M");
 144  
         }
 145  0
         sb.append(")");
 146  0
         if (mu.getMax() >= 0) {
 147  0
             sb.append(" / ");
 148  0
             sb.append(mu.getMax());
 149  0
             if (inMegs) {
 150  0
                 sb.append("M");
 151  
             }
 152  0
             sb.append(" - ");
 153  0
             if (mu.getMax() > 0) {
 154  0
                 sb.append(mu.getUsed() * HUNDRED_PERCENT / mu.getMax());
 155  
             } else {
 156  0
                 sb.append('0');
 157  
             }
 158  0
             sb.append('%');
 159  
         } else {
 160  0
             sb.append(" / ?");
 161  
         }
 162  0
         sb.append(']');
 163  0
         return sb.toString();
 164  
     }
 165  
 
 166  
     /**
 167  
      * Returns memory usage in the following format: xx%
 168  
      * @param mu the memory usage object, may be null
 169  
      * @return formatted percent value; "not available" if the object is null or max is -1; "none" if max is zero
 170  
      */
 171  
     public static String getUsagePerc(final MemoryUsage mu) {
 172  24
         if (mu == null || mu.getMax() < 0) {
 173  0
             return "not available";
 174  
         }
 175  24
         if (mu.getMax() == 0) {
 176  0
             return "none";
 177  
         }
 178  24
         return (mu.getUsed() * HUNDRED_PERCENT / mu.getMax()) + "%";
 179  
     }
 180  
 
 181  
     /**
 182  
      * Returns amount of free memory in the following format: xx%
 183  
      * @param mu the memory usage object, may be null
 184  
      * @return formatted percent value; "?" if the object is null or max is -1; "none" if max is zero
 185  
      */
 186  
     public static String getFreePerc(final MemoryUsage mu) {
 187  0
         if (mu == null || mu.getMax() < 0) {
 188  0
             return "not available";
 189  
         }
 190  0
         if (mu.getMax() == 0) {
 191  0
             return "none";
 192  
         }
 193  0
         return (HUNDRED_PERCENT - (mu.getUsed() * HUNDRED_PERCENT / mu.getMax())) + "%";
 194  
     }
 195  
     private static final SortedMap<String, MemoryPoolMXBean> MEMORY_POOLS;
 196  
 
 197  
     static {
 198  1
         final SortedMap<String, MemoryPoolMXBean> pools = new TreeMap<String, MemoryPoolMXBean>();
 199  
         try {
 200  1
             final List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans();
 201  1
             if (beans != null && !beans.isEmpty()) {
 202  1
                 for (final MemoryPoolMXBean bean : beans) {
 203  5
                     final MemoryUsage usage = bean.getUsage();
 204  5
                     if (usage == null || !bean.isUsageThresholdSupported()) {
 205  2
                         continue;
 206  
                     }
 207  3
                     pools.put(bean.getName(), bean);
 208  3
                 }
 209  
             }
 210  0
         } catch (Exception ex) {
 211  0
             LOG.log(Level.SEVERE, "Failed to get MemoryPools: " + ex, ex);
 212  1
         }
 213  1
         MEMORY_POOLS = Collections.unmodifiableSortedMap(pools);
 214  1
     }
 215  
 
 216  
     /**
 217  
      * Returns all known memory pools which are garbage-collectable and provide meaningful usage information.
 218  
      * @return map of memory pools, never null, may be empty.
 219  
      */
 220  
     public static SortedMap<String, MemoryPoolMXBean> getMemoryPools() {
 221  0
         return MEMORY_POOLS;
 222  
     }
 223  
 }