Coverage Report - sk.baka.webvm.analyzer.hostos.Memory
 
Classes in this File Line Coverage Branch Coverage Complexity
Memory
58%
7/12
50%
2/4
3.917
Memory$MemoryJMXStrategy
0%
0/29
0%
0/6
3.917
Memory$MemoryLinuxStrategy
73%
41/56
59%
13/22
3.917
 
 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.analyzer.hostos;
 20  
 
 21  
 import java.io.BufferedReader;
 22  
 import java.io.FileReader;
 23  
 import java.io.IOException;
 24  
 import java.lang.management.ManagementFactory;
 25  
 import java.lang.management.MemoryUsage;
 26  
 import java.lang.management.OperatingSystemMXBean;
 27  
 import java.util.HashMap;
 28  
 import java.util.Map;
 29  
 import java.util.logging.Level;
 30  
 import java.util.logging.Logger;
 31  
 import sk.baka.tools.IOUtils;
 32  
 import static sk.baka.webvm.misc.Constants.*;
 33  
 
 34  
 /**
 35  
  * Delivers information from a host operating system.
 36  
  * @author Martin Vysny
 37  
  */
 38  0
 public final class Memory {
 39  
 
 40  1
     private static final Logger LOG = Logger.getLogger(Memory.class.getName());
 41  
 
 42  
     /**
 43  
      * Returns physical memory information for host OS.
 44  
      * @return memory usage or null if the information is unavailable. The committed memory size includes buffers and/or disk cache. If committed memory size is equal to the used memory size then the buffer/cache information is not available.
 45  
      */
 46  
     public static MemoryUsage getPhysicalMemory() {
 47  14
         MemoryUsage result = MemoryLinuxStrategy.getPhysicalMemory();
 48  14
         if (result != null) {
 49  14
             return result;
 50  
         }
 51  0
         return MemoryJMXStrategy.getPhysicalMemory();
 52  
     }
 53  
 
 54  
     /**
 55  
      * Returns swap memory information for host OS.
 56  
      * @return memory usage or null if the information is unavailable.
 57  
      */
 58  
     public static MemoryUsage getSwap() {
 59  14
         MemoryUsage result = MemoryLinuxStrategy.getSwap();
 60  14
         if (result != null) {
 61  14
             return result;
 62  
         }
 63  0
         return MemoryJMXStrategy.getSwap();
 64  
     }
 65  
 
 66  
     /**
 67  
      * Retrieves host OS memory info using /proc/meminfo (Linux only)
 68  
      */
 69  
     private static final class MemoryLinuxStrategy {
 70  
 
 71  
         private static final boolean AVAIL;
 72  
         private static final String MEMINFO = "/proc/meminfo";
 73  
 
 74  
         private static Map<String, Long> parseMeminfo(final String memInfo) throws IOException {
 75  29
             final Map<String, Long> result = new HashMap<String, Long>();
 76  29
             final BufferedReader in = new BufferedReader(new FileReader(memInfo));
 77  
             try {
 78  1247
                 for (String line = in.readLine(); line != null; line = in.readLine()) {
 79  1218
                     int colon = line.indexOf(':');
 80  1218
                     if (colon < 0) {
 81  0
                         continue;
 82  
                     }
 83  1218
                     final String key = line.substring(0, colon);
 84  1218
                     String value = line.substring(colon + 1, line.length()).trim();
 85  1218
                     if (value.endsWith(" kB")) {
 86  1102
                         value = value.substring(0, value.length() - " kB".length());
 87  
                     }
 88  
                     try {
 89  1218
                         final long val = Long.parseLong(value);
 90  1218
                         result.put(key, val);
 91  0
                     } catch (NumberFormatException ex) {
 92  0
                         continue;
 93  1218
                     }
 94  
                 }
 95  
             } finally {
 96  29
                 IOUtils.closeQuietly(in);
 97  29
             }
 98  29
             return result;
 99  
         }
 100  
 
 101  
 
 102  
         static {
 103  1
             boolean avail = false;
 104  
             try {
 105  1
                 parseMeminfo(MEMINFO);
 106  1
                 avail = true;
 107  0
             } catch (Exception ex) {
 108  0
                 LOG.log(Level.INFO, "MemoryLinuxStrategy disabled: " + MEMINFO + " not available", ex);
 109  1
             }
 110  1
             AVAIL = avail;
 111  1
         }
 112  
 
 113  
         /**
 114  
          * Checks that this strategy is available to use.
 115  
          * @return true if available, false otherwise.
 116  
          */
 117  
         public static boolean available() {
 118  28
             return AVAIL;
 119  
         }
 120  
 
 121  
         /**
 122  
          * Returns physical memory information for host OS.
 123  
          * @return memory usage or null if the information is unavailable.
 124  
          */
 125  
         public static MemoryUsage getPhysicalMemory() {
 126  14
             if (!available()) {
 127  0
                 return null;
 128  
             }
 129  
             final Map<String, Long> memInfo;
 130  
             try {
 131  14
                 memInfo = parseMeminfo(MEMINFO);
 132  0
             } catch (Exception t) {
 133  0
                 return null;
 134  14
             }
 135  14
             final Long total = memInfo.get("MemTotal");
 136  14
             final Long free = memInfo.get("MemFree");
 137  14
             final Long buffers = memInfo.get("Buffers");
 138  14
             final Long cache = memInfo.get("Cached");
 139  14
             if (total == null || free == null || buffers == null || cache == null) {
 140  0
                 return null;
 141  
             }
 142  14
             final long committed = total - free;
 143  14
             final long used = committed - buffers - cache;
 144  14
             return new MemoryUsage(-1, used * KIBIBYTES, committed * KIBIBYTES, total * KIBIBYTES);
 145  
         }
 146  
 
 147  
         /**
 148  
          * Returns physical memory information for host OS.
 149  
          * @return memory usage or null if the information is unavailable.
 150  
          */
 151  
         public static MemoryUsage getSwap() {
 152  14
             if (!available()) {
 153  0
                 return null;
 154  
             }
 155  
             final Map<String, Long> memInfo;
 156  
             try {
 157  14
                 memInfo = parseMeminfo(MEMINFO);
 158  0
             } catch (Exception t) {
 159  0
                 return null;
 160  14
             }
 161  14
             final Long total = memInfo.get("SwapTotal");
 162  14
             final Long free = memInfo.get("SwapFree");
 163  14
             if (total == null || free == null) {
 164  0
                 return null;
 165  
             }
 166  14
             final long used = total - free;
 167  14
             return new MemoryUsage(-1, used * KIBIBYTES, used * KIBIBYTES, total * KIBIBYTES);
 168  
         }
 169  
 
 170  0
         private MemoryLinuxStrategy() {
 171  0
             throw new AssertionError();
 172  
         }
 173  
     }
 174  
 
 175  
     /**
 176  
      * Retrieves host OS memory info using com.sun.management.OperatingSystemMXBean
 177  
      */
 178  
     private static final class MemoryJMXStrategy {
 179  
 
 180  
         private static final OperatingSystemMXBean BEAN;
 181  
         private static final Class<?> BEAN_CLASS;
 182  
 
 183  
         static {
 184  0
             OperatingSystemMXBean b = null;
 185  0
             Class<?> clazz = null;
 186  
             try {
 187  0
                 clazz = Class.forName("com.sun.management.OperatingSystemMXBean");
 188  0
                 b = OperatingSystemMXBean.class.cast(clazz.cast(ManagementFactory.getOperatingSystemMXBean()));
 189  0
             } catch (ClassNotFoundException ex) {
 190  0
                 LOG.log(Level.INFO, "MemoryJMXStrategy disabled: com.sun.management.OperatingSystemMXBean unavailable", ex);
 191  0
             }
 192  0
             BEAN = b;
 193  0
             BEAN_CLASS = clazz;
 194  0
         }
 195  
 
 196  
         /**
 197  
          * Checks that this strategy is available to use.
 198  
          * @return true if available, false otherwise.
 199  
          */
 200  
         public static boolean available() {
 201  0
             return BEAN != null;
 202  
         }
 203  
 
 204  
         /**
 205  
          * Returns physical memory information for host OS.
 206  
          * @return memory usage or null if the information is unavailable.
 207  
          */
 208  
         public static MemoryUsage getPhysicalMemory() {
 209  0
             if (!available()) {
 210  0
                 return null;
 211  
             }
 212  
             try {
 213  0
                 final long total = (Long) BEAN_CLASS.getMethod("getTotalPhysicalMemorySize").invoke(BEAN);
 214  0
                 final long free = (Long) BEAN_CLASS.getMethod("getFreePhysicalMemorySize").invoke(BEAN);
 215  0
                 final long used = total - free;
 216  0
                 return new MemoryUsage(-1, used, used, total);
 217  0
             } catch (Exception e) {
 218  0
                 return null;
 219  
             }
 220  
         }
 221  
 
 222  
         /**
 223  
          * Returns physical memory information for host OS.
 224  
          * @return memory usage or null if the information is unavailable.
 225  
          */
 226  
         public static MemoryUsage getSwap() {
 227  0
             if (!available()) {
 228  0
                 return null;
 229  
             }
 230  
             try {
 231  0
                 final long total = (Long) BEAN_CLASS.getMethod("getTotalSwapSpaceSize").invoke(BEAN);
 232  0
                 final long free = (Long) BEAN_CLASS.getMethod("getFreeSwapSpaceSize").invoke(BEAN);
 233  0
                 final long used = total - free;
 234  0
                 return new MemoryUsage(-1, used, used, total);
 235  0
             } catch (Exception e) {
 236  0
                 return null;
 237  
             }
 238  
         }
 239  
 
 240  0
         private MemoryJMXStrategy() {
 241  0
             throw new AssertionError();
 242  
         }
 243  
     }
 244  
 
 245  0
     private Memory() {
 246  0
         throw new AssertionError();
 247  
     }
 248  
 }