View Javadoc
1   /*
2    * Copyright 2016-2024 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.common;
6   
7   import java.util.ArrayList;
8   import java.util.List;
9   
10  import oshi.annotation.concurrent.ThreadSafe;
11  import oshi.hardware.GlobalMemory;
12  import oshi.hardware.PhysicalMemory;
13  import oshi.util.Constants;
14  import oshi.util.ExecutingCommand;
15  import oshi.util.FormatUtil;
16  import oshi.util.ParseUtil;
17  
18  /**
19   * Memory info.
20   */
21  @ThreadSafe
22  public abstract class AbstractGlobalMemory implements GlobalMemory {
23  
24      @Override
25      public List<PhysicalMemory> getPhysicalMemory() {
26          // dmidecode requires sudo permission but is the only option on Linux
27          // and Unix
28          List<PhysicalMemory> pmList = new ArrayList<>();
29          List<String> dmi = ExecutingCommand.runNative("dmidecode --type 17");
30          int bank = 0;
31          String bankLabel = Constants.UNKNOWN;
32          String locator = "";
33          long capacity = 0L;
34          long speed = 0L;
35          String manufacturer = Constants.UNKNOWN;
36          String memoryType = Constants.UNKNOWN;
37          String partNumber = Constants.UNKNOWN;
38          String serialNumber = Constants.UNKNOWN;
39          for (String line : dmi) {
40              if (line.trim().contains("DMI type 17")) {
41                  // Save previous bank
42                  if (bank++ > 0) {
43                      if (capacity > 0) {
44                          pmList.add(new PhysicalMemory(bankLabel + locator, capacity, speed, manufacturer, memoryType,
45                                  partNumber, serialNumber));
46                      }
47                      bankLabel = Constants.UNKNOWN;
48                      locator = "";
49                      capacity = 0L;
50                      speed = 0L;
51                  }
52              } else if (bank > 0) {
53                  String[] split = line.trim().split(":");
54                  if (split.length == 2) {
55                      switch (split[0]) {
56                      case "Bank Locator":
57                          bankLabel = split[1].trim();
58                          break;
59                      case "Locator":
60                          locator = "/" + split[1].trim();
61                          break;
62                      case "Size":
63                          capacity = ParseUtil.parseDecimalMemorySizeToBinary(split[1].trim());
64                          break;
65                      case "Type":
66                          memoryType = split[1].trim();
67                          break;
68                      case "Speed":
69                          speed = ParseUtil.parseHertz(split[1]);
70                          break;
71                      case "Manufacturer":
72                          manufacturer = split[1].trim();
73                          break;
74                      case "PartNumber":
75                      case "Part Number":
76                          partNumber = split[1].trim();
77                          break;
78                      case "Serial Number":
79                          serialNumber = split[1].trim();
80                          break;
81                      default:
82                          break;
83                      }
84                  }
85              }
86          }
87          if (capacity > 0) {
88              pmList.add(new PhysicalMemory(bankLabel + locator, capacity, speed, manufacturer, memoryType, partNumber,
89                      serialNumber));
90          }
91          return pmList;
92      }
93  
94      @Override
95      public String toString() {
96          StringBuilder sb = new StringBuilder();
97          sb.append("Available: ");
98          sb.append(FormatUtil.formatBytes(getAvailable()));
99          sb.append("/");
100         sb.append(FormatUtil.formatBytes(getTotal()));
101         return sb.toString();
102     }
103 }