1
2
3
4
5 package oshi.driver.windows.wmi;
6
7 import static oshi.util.Memoizer.memoize;
8
9 import java.util.HashMap;
10 import java.util.Map;
11 import java.util.concurrent.locks.ReentrantLock;
12 import java.util.function.Supplier;
13
14 import com.sun.jna.platform.win32.COM.WbemcliUtil.WmiResult;
15
16 import oshi.annotation.concurrent.GuardedBy;
17 import oshi.annotation.concurrent.ThreadSafe;
18 import oshi.driver.windows.wmi.Win32Process.CommandLineProperty;
19 import oshi.util.platform.windows.WmiUtil;
20 import oshi.util.tuples.Pair;
21
22
23
24
25 @ThreadSafe
26 public final class Win32ProcessCached {
27
28 private static final Supplier<Win32ProcessCached> INSTANCE = memoize(Win32ProcessCached::createInstance);
29
30
31 @GuardedBy("commandLineCacheLock")
32 private final Map<Integer, Pair<Long, String>> commandLineCache = new HashMap<>();
33 private final ReentrantLock commandLineCacheLock = new ReentrantLock();
34
35 private Win32ProcessCached() {
36 }
37
38
39
40
41
42
43 public static Win32ProcessCached getInstance() {
44 return INSTANCE.get();
45 }
46
47 private static Win32ProcessCached createInstance() {
48 return new Win32ProcessCached();
49 }
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 public String getCommandLine(int processId, long startTime) {
72
73 commandLineCacheLock.lock();
74 try {
75
76 Pair<Long, String> pair = commandLineCache.get(processId);
77
78 if (pair != null && startTime < pair.getA()) {
79
80 return pair.getB();
81 } else {
82
83
84 long now = System.currentTimeMillis();
85
86 WmiResult<CommandLineProperty> commandLineAllProcs = Win32Process.queryCommandLines(null);
87
88
89 if (commandLineCache.size() > commandLineAllProcs.getResultCount() * 2) {
90 commandLineCache.clear();
91 }
92
93 String result = "";
94 for (int i = 0; i < commandLineAllProcs.getResultCount(); i++) {
95 int pid = WmiUtil.getUint32(commandLineAllProcs, CommandLineProperty.PROCESSID, i);
96 String cl = WmiUtil.getString(commandLineAllProcs, CommandLineProperty.COMMANDLINE, i);
97 commandLineCache.put(pid, new Pair<>(now, cl));
98 if (pid == processId) {
99 result = cl;
100 }
101 }
102 return result;
103 }
104 } finally {
105 commandLineCacheLock.unlock();
106 }
107 }
108 }