View Javadoc
1   /**
2    * Oshi (https://github.com/dblock/oshi)
3    * 
4    * Copyright (c) 2010 - 2015 The Oshi Project Team
5    * 
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of the Eclipse Public License v1.0
8    * which accompanies this distribution, and is available at
9    * http://www.eclipse.org/legal/epl-v10.html
10   * 
11   * Contributors:
12   * dblock[at]dblock[dot]org
13   * alessandro[at]perucchi[dot]org
14   * widdis[at]gmail[dot]com
15   * https://github.com/dblock/oshi/graphs/contributors
16   */
17  package oshi.software.os.linux.proc;
18  
19  import java.io.IOException;
20  import java.util.List;
21  
22  import oshi.hardware.Memory;
23  import oshi.software.os.linux.Libc;
24  import oshi.software.os.linux.Libc.Sysinfo;
25  import oshi.util.FileUtil;
26  
27  import com.sun.jna.LastErrorException;
28  import com.sun.jna.Native;
29  
30  /**
31   * Memory obtained by /proc/meminfo and sysinfo.totalram
32   * 
33   * @author alessandro[at]perucchi[dot]org
34   * @author widdis[at]gmail[dot]com
35   */
36  public class GlobalMemory implements Memory {
37  
38  	private long totalMemory = 0;
39  
40  	@Override
41  	public long getAvailable() {
42  		long availableMemory = 0;
43  		List<String> memInfo = null;
44  		try {
45  			memInfo = FileUtil.readFile("/proc/meminfo");
46  		} catch (IOException e) {
47  			System.err.println("Problem with: /proc/meminfo");
48  			System.err.println(e.getMessage());
49  			return availableMemory;
50  		}
51  		for (String checkLine : memInfo) {
52  			// If we have MemAvailable, it trumps all. See code in
53  			// https://git.kernel.org/cgit/linux/kernel/git/torvalds/
54  			// linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
55  			if (checkLine.startsWith("MemAvailable:")) {
56  				String[] memorySplit = checkLine.split("\\s+");
57  				availableMemory = parseMeminfo(memorySplit);
58  				break;
59  			} else
60  			// Otherwise we combine MemFree + Active(file), Inactive(file), and
61  			// SReclaimable. Free+cached is no longer appropriate. MemAvailable
62  			// reduces these values using watermarks to estimate when swapping
63  			// is prevented, omitted here for simplicity (assuming 0 swap).
64  			if (checkLine.startsWith("MemFree:")) {
65  				String[] memorySplit = checkLine.split("\\s+");
66  				availableMemory += parseMeminfo(memorySplit);
67  			} else if (checkLine.startsWith("Active(file):")) {
68  				String[] memorySplit = checkLine.split("\\s+");
69  				availableMemory += parseMeminfo(memorySplit);
70  			} else if (checkLine.startsWith("Inactive(file):")) {
71  				String[] memorySplit = checkLine.split("\\s+");
72  				availableMemory += parseMeminfo(memorySplit);
73  			} else if (checkLine.startsWith("SReclaimable:")) {
74  				String[] memorySplit = checkLine.split("\\s+");
75  				availableMemory += parseMeminfo(memorySplit);
76  			}
77  		}
78  		return availableMemory;
79  	}
80  
81  	@Override
82  	public long getTotal() {
83  		if (this.totalMemory == 0) {
84  			Sysinfo info = new Sysinfo();
85  			if (0 != Libc.INSTANCE.sysinfo(info))
86  				throw new LastErrorException("Error code: "
87  						+ Native.getLastError());
88  			this.totalMemory = info.totalram.longValue() * info.mem_unit;
89  		}
90  		return this.totalMemory;
91  	}
92  
93  	private long parseMeminfo(String[] memorySplit) {
94  		if (memorySplit.length < 2) {
95  			return 0l;
96  		}
97  		long memory = new Long(memorySplit[1]).longValue();
98  		if (memorySplit.length > 2 && memorySplit[2].equals("kB")) {
99  			memory *= 1024;
100 		}
101 		return memory;
102 	}
103 }