1
2
3
4
5 package oshi.hardware.platform.mac;
6
7 import static oshi.util.Memoizer.defaultExpiration;
8 import static oshi.util.Memoizer.memoize;
9
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.function.Supplier;
13
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 import com.sun.jna.Native;
18 import com.sun.jna.platform.mac.SystemB;
19
20 import oshi.annotation.concurrent.ThreadSafe;
21 import oshi.hardware.PhysicalMemory;
22 import oshi.hardware.VirtualMemory;
23 import oshi.hardware.common.AbstractGlobalMemory;
24 import oshi.jna.ByRef.CloseableIntByReference;
25 import oshi.jna.ByRef.CloseableLongByReference;
26 import oshi.jna.Struct.CloseableVMStatistics;
27 import oshi.util.Constants;
28 import oshi.util.ExecutingCommand;
29 import oshi.util.ParseUtil;
30 import oshi.util.platform.mac.SysctlUtil;
31
32
33
34
35 @ThreadSafe
36 final class MacGlobalMemory extends AbstractGlobalMemory {
37
38 private static final Logger LOG = LoggerFactory.getLogger(MacGlobalMemory.class);
39
40 private final Supplier<Long> available = memoize(this::queryVmStats, defaultExpiration());
41
42 private final Supplier<Long> total = memoize(MacGlobalMemory::queryPhysMem);
43
44 private final Supplier<Long> pageSize = memoize(MacGlobalMemory::queryPageSize);
45
46 private final Supplier<VirtualMemory> vm = memoize(this::createVirtualMemory);
47
48 @Override
49 public long getAvailable() {
50 return available.get();
51 }
52
53 @Override
54 public long getTotal() {
55 return total.get();
56 }
57
58 @Override
59 public long getPageSize() {
60 return pageSize.get();
61 }
62
63 @Override
64 public VirtualMemory getVirtualMemory() {
65 return vm.get();
66 }
67
68 @Override
69 public List<PhysicalMemory> getPhysicalMemory() {
70 List<PhysicalMemory> pmList = new ArrayList<>();
71 List<String> sp = ExecutingCommand.runNative("system_profiler SPMemoryDataType");
72 int bank = 0;
73 String bankLabel = Constants.UNKNOWN;
74 long capacity = 0L;
75 long speed = 0L;
76 String manufacturer = Constants.UNKNOWN;
77 String memoryType = Constants.UNKNOWN;
78 String partNumber = Constants.UNKNOWN;
79 String serialNumber = Constants.UNKNOWN;
80 for (String line : sp) {
81 if (line.trim().startsWith("BANK")) {
82
83 if (bank++ > 0) {
84 pmList.add(new PhysicalMemory(bankLabel, capacity, speed, manufacturer, memoryType,
85 Constants.UNKNOWN, serialNumber));
86 }
87 bankLabel = line.trim();
88 int colon = bankLabel.lastIndexOf(':');
89 if (colon > 0) {
90 bankLabel = bankLabel.substring(0, colon - 1);
91 }
92 } else if (bank > 0) {
93 String[] split = line.trim().split(":");
94 if (split.length == 2) {
95 switch (split[0]) {
96 case "Size":
97 capacity = ParseUtil.parseDecimalMemorySizeToBinary(split[1].trim());
98 break;
99 case "Type":
100 memoryType = split[1].trim();
101 break;
102 case "Speed":
103 speed = ParseUtil.parseHertz(split[1]);
104 break;
105 case "Manufacturer":
106 manufacturer = split[1].trim();
107 break;
108 case "Part Number":
109 partNumber = split[1].trim();
110 break;
111 case "Serial Number":
112 serialNumber = split[1].trim();
113 break;
114 default:
115 break;
116 }
117 }
118 }
119 }
120 pmList.add(new PhysicalMemory(bankLabel, capacity, speed, manufacturer, memoryType, partNumber, serialNumber));
121
122 return pmList;
123 }
124
125 private long queryVmStats() {
126 try (CloseableVMStatistics vmStats = new CloseableVMStatistics();
127 CloseableIntByReference size = new CloseableIntByReference(vmStats.size() / SystemB.INT_SIZE)) {
128 if (0 != SystemB.INSTANCE.host_statistics(SystemB.INSTANCE.mach_host_self(), SystemB.HOST_VM_INFO, vmStats,
129 size)) {
130 LOG.error("Failed to get host VM info. Error code: {}", Native.getLastError());
131 return 0L;
132 }
133 return (vmStats.free_count + vmStats.inactive_count) * getPageSize();
134 }
135 }
136
137 private static long queryPhysMem() {
138 return SysctlUtil.sysctl("hw.memsize", 0L);
139 }
140
141 private static long queryPageSize() {
142 try (CloseableLongByReference pPageSize = new CloseableLongByReference()) {
143 if (0 == SystemB.INSTANCE.host_page_size(SystemB.INSTANCE.mach_host_self(), pPageSize)) {
144 return pPageSize.getValue();
145 }
146 }
147 LOG.error("Failed to get host page size. Error code: {}", Native.getLastError());
148 return 4098L;
149 }
150
151 private VirtualMemory createVirtualMemory() {
152 return new MacVirtualMemory(this);
153 }
154 }