1
2
3
4
5 package oshi.demo.gui;
6
7 import java.awt.BorderLayout;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Locale;
12 import java.util.Map;
13 import java.util.Map.Entry;
14
15 import javax.swing.ButtonGroup;
16 import javax.swing.JLabel;
17 import javax.swing.JPanel;
18 import javax.swing.JRadioButton;
19 import javax.swing.JScrollPane;
20 import javax.swing.JTable;
21 import javax.swing.ScrollPaneConstants;
22 import javax.swing.Timer;
23 import javax.swing.table.DefaultTableModel;
24 import javax.swing.table.TableColumn;
25 import javax.swing.table.TableColumnModel;
26 import javax.swing.table.TableModel;
27
28 import oshi.PlatformEnum;
29 import oshi.SystemInfo;
30 import oshi.software.os.OSProcess;
31 import oshi.software.os.OperatingSystem;
32 import oshi.util.FormatUtil;
33
34
35
36
37
38 public class ProcessPanel extends OshiJPanel {
39
40 private static final long serialVersionUID = 1L;
41
42 private static final String PROCESSES = "Processes";
43 private static final String[] COLUMNS = { "PID", "PPID", "Threads", "% CPU", "Cumulative", "VSZ", "RSS", "% Memory",
44 "Process Name" };
45 private static final double[] COLUMN_WIDTH_PERCENT = { 0.07, 0.07, 0.07, 0.07, 0.09, 0.1, 0.1, 0.08, 0.35 };
46
47 private transient Map<Integer, OSProcess> priorSnapshotMap = new HashMap<>();
48
49 private transient ButtonGroup cpuOption = new ButtonGroup();
50 private transient JRadioButton perProc = new JRadioButton("of one Processor");
51 private transient JRadioButton perSystem = new JRadioButton("of System");
52
53 private transient ButtonGroup sortOption = new ButtonGroup();
54 private transient JRadioButton cpuButton = new JRadioButton("CPU %");
55 private transient JRadioButton cumulativeCpuButton = new JRadioButton("Cumulative CPU");
56 private transient JRadioButton memButton = new JRadioButton("Memory %");
57
58 public ProcessPanel(SystemInfo si) {
59 super();
60 init(si);
61 }
62
63 private void init(SystemInfo si) {
64 OperatingSystem os = si.getOperatingSystem();
65 JLabel procLabel = new JLabel(PROCESSES);
66 add(procLabel, BorderLayout.NORTH);
67
68 JPanel settings = new JPanel();
69
70 JLabel cpuChoice = new JLabel(" CPU %:");
71 settings.add(cpuChoice);
72 cpuOption.add(perProc);
73 settings.add(perProc);
74 cpuOption.add(perSystem);
75 settings.add(perSystem);
76 if (SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) {
77 perSystem.setSelected(true);
78 } else {
79 perProc.setSelected(true);
80 }
81
82 JLabel sortChoice = new JLabel(" Sort by:");
83 settings.add(sortChoice);
84 sortOption.add(cpuButton);
85 settings.add(cpuButton);
86 sortOption.add(cumulativeCpuButton);
87 settings.add(cumulativeCpuButton);
88 sortOption.add(memButton);
89 settings.add(memButton);
90 cpuButton.setSelected(true);
91
92 TableModel model = new DefaultTableModel(parseProcesses(os.getProcesses(null, null, 0), si), COLUMNS);
93 JTable procTable = new JTable(model);
94 JScrollPane scrollV = new JScrollPane(procTable);
95 scrollV.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
96 resizeColumns(procTable.getColumnModel());
97
98 add(scrollV, BorderLayout.CENTER);
99 add(settings, BorderLayout.SOUTH);
100
101 Timer timer = new Timer(Config.REFRESH_SLOW, e -> {
102 DefaultTableModel tableModel = (DefaultTableModel) procTable.getModel();
103 Object[][] newData = parseProcesses(os.getProcesses(null, null, 0), si);
104 int rowCount = tableModel.getRowCount();
105 for (int row = 0; row < newData.length; row++) {
106 if (row < rowCount) {
107
108 for (int col = 0; col < newData[row].length; col++) {
109 tableModel.setValueAt(newData[row][col], row, col);
110 }
111 } else {
112
113 tableModel.addRow(newData[row]);
114 }
115 }
116
117 for (int row = rowCount - 1; row >= newData.length; row--) {
118 tableModel.removeRow(row);
119 }
120 });
121 timer.start();
122 }
123
124 private Object[][] parseProcesses(List<OSProcess> list, SystemInfo si) {
125 long totalMem = si.getHardware().getMemory().getTotal();
126 int cpuCount = si.getHardware().getProcessor().getLogicalProcessorCount();
127
128 Map<OSProcess, Double> processSortValueMap = new HashMap<>();
129 for (OSProcess p : list) {
130 int pid = p.getProcessID();
131
132 if (pid > 0 || !SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) {
133
134 if (cpuButton.isSelected()) {
135 processSortValueMap.put(p, p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid)));
136 } else if (cumulativeCpuButton.isSelected()) {
137 processSortValueMap.put(p, p.getProcessCpuLoadCumulative());
138 } else {
139 processSortValueMap.put(p, (double) p.getResidentSetSize());
140 }
141 }
142 }
143
144 List<Entry<OSProcess, Double>> procList = new ArrayList<>(processSortValueMap.entrySet());
145 procList.sort(Entry.comparingByValue());
146
147 int i = procList.size();
148 Object[][] procArr = new Object[i][COLUMNS.length];
149
150 for (Entry<OSProcess, Double> e : procList) {
151 OSProcess p = e.getKey();
152
153 i--;
154 int pid = p.getProcessID();
155 procArr[i][0] = pid;
156 procArr[i][1] = p.getParentProcessID();
157 procArr[i][2] = p.getThreadCount();
158 if (perProc.isSelected()) {
159 procArr[i][3] = String.format(Locale.ROOT, "%.1f",
160 100d * p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid)) * cpuCount);
161 procArr[i][4] = String.format(Locale.ROOT, "%.1f", 100d * p.getProcessCpuLoadCumulative() * cpuCount);
162 } else {
163 procArr[i][3] = String.format(Locale.ROOT, "%.1f",
164 100d * p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid)));
165 procArr[i][4] = String.format(Locale.ROOT, "%.1f", 100d * p.getProcessCpuLoadCumulative());
166 }
167 procArr[i][5] = FormatUtil.formatBytes(p.getVirtualSize());
168 procArr[i][6] = FormatUtil.formatBytes(p.getResidentSetSize());
169 procArr[i][7] = String.format(Locale.ROOT, "%.1f", 100d * p.getResidentSetSize() / totalMem);
170 procArr[i][8] = p.getName();
171 }
172
173 priorSnapshotMap.clear();
174 for (OSProcess p : list) {
175 priorSnapshotMap.put(p.getProcessID(), p);
176 }
177 return procArr;
178 }
179
180 private static void resizeColumns(TableColumnModel tableColumnModel) {
181 TableColumn column;
182 int tW = tableColumnModel.getTotalColumnWidth();
183 int cantCols = tableColumnModel.getColumnCount();
184 for (int i = 0; i < cantCols; i++) {
185 column = tableColumnModel.getColumn(i);
186 int pWidth = (int) Math.round(COLUMN_WIDTH_PERCENT[i] * tW);
187 column.setPreferredWidth(pWidth);
188 }
189 }
190 }