|
8 | 8 | import java.io.IOException;
|
9 | 9 | import java.io.InputStreamReader;
|
10 | 10 | import java.lang.management.ManagementFactory;
|
| 11 | +import java.nio.file.Files; |
| 12 | +import java.nio.file.Path; |
| 13 | +import java.nio.file.Paths; |
11 | 14 | import java.util.Collections;
|
12 | 15 | import java.util.Set;
|
13 | 16 | import java.util.concurrent.CompletableFuture;
|
14 | 17 | import java.util.concurrent.TimeUnit;
|
15 | 18 | import java.util.function.Supplier;
|
| 19 | +import java.util.stream.Collectors; |
| 20 | +import java.util.stream.Stream; |
16 | 21 | import org.slf4j.Logger;
|
17 | 22 | import org.slf4j.LoggerFactory;
|
18 | 23 |
|
@@ -64,12 +69,48 @@ private static String findPid() {
|
64 | 69 | return pid;
|
65 | 70 | }
|
66 | 71 |
|
| 72 | + private static String getOSTempDir() { |
| 73 | + // See |
| 74 | + // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha#remarks |
| 75 | + // and |
| 76 | + // the JDK OS-specific implementations of os::get_temp_directory(), i.e. |
| 77 | + // https://github.com/openjdk/jdk/blob/f50bd0d9ec65a6b9596805d0131aaefc1bb913f3/src/hotspot/os/bsd/os_bsd.cpp#L886-L904 |
| 78 | + if (Platform.isLinux()) { |
| 79 | + return "/tmp/"; |
| 80 | + } else if (Platform.isWindows()) { |
| 81 | + return Stream.of(System.getenv("TMP"), System.getenv("TEMP"), System.getenv("USERPROFILE")) |
| 82 | + .filter(String::isEmpty) |
| 83 | + .findFirst() |
| 84 | + .orElse("C:\\Windows"); |
| 85 | + } else if (Platform.isMac()) { |
| 86 | + return System.getenv("TMPDIR"); |
| 87 | + } else { |
| 88 | + return System.getProperty("java.io.tmpdir"); |
| 89 | + } |
| 90 | + } |
| 91 | + |
67 | 92 | public static Set<String> getJavaPids() {
|
68 | 93 | // Attempt to use jvmstat directly, fall through to jps process fork strategy
|
69 | 94 | Set<String> directlyObtainedPids = JPSUtils.getVMPids();
|
70 | 95 | if (directlyObtainedPids != null) {
|
71 | 96 | return directlyObtainedPids;
|
72 | 97 | }
|
| 98 | + |
| 99 | + // Some JDKs don't have jvmstat available as a module, attempt to read from the hsperfdata |
| 100 | + // directory instead |
| 101 | + try (Stream<Path> stream = |
| 102 | + // Emulating the hotspot way to enumerate the JVM processes using the perfdata file |
| 103 | + // https://github.com/openjdk/jdk/blob/d7cb933b89839b692f5562aeeb92076cd25a99f6/src/hotspot/share/runtime/perfMemory.cpp#L244 |
| 104 | + Files.list(Paths.get(getOSTempDir(), "hsperfdata_" + System.getProperty("user.name")))) { |
| 105 | + return stream |
| 106 | + .filter(file -> !Files.isDirectory(file)) |
| 107 | + .map(Path::getFileName) |
| 108 | + .map(Path::toString) |
| 109 | + .collect(Collectors.toSet()); |
| 110 | + } catch (IOException e) { |
| 111 | + log.debug("Unable to obtain Java PIDs via hsperfdata", e); |
| 112 | + } |
| 113 | + |
73 | 114 | // there is no supported Java API to achieve this
|
74 | 115 | // one could use sun.jvmstat.monitor.MonitoredHost but it is an internal API and can go away at
|
75 | 116 | // any time -
|
|
0 commit comments