diff --git a/internal-api/src/main/java/datadog/trace/util/PidHelper.java b/internal-api/src/main/java/datadog/trace/util/PidHelper.java index dfa6276b879..eebf6fa7449 100644 --- a/internal-api/src/main/java/datadog/trace/util/PidHelper.java +++ b/internal-api/src/main/java/datadog/trace/util/PidHelper.java @@ -8,11 +8,16 @@ import java.io.IOException; import java.io.InputStreamReader; import java.lang.management.ManagementFactory; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collections; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,12 +69,48 @@ private static String findPid() { return pid; } + private static String getOSTempDir() { + // See + // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha#remarks + // and + // the JDK OS-specific implementations of os::get_temp_directory(), i.e. + // https://github.com/openjdk/jdk/blob/f50bd0d9ec65a6b9596805d0131aaefc1bb913f3/src/hotspot/os/bsd/os_bsd.cpp#L886-L904 + if (Platform.isLinux()) { + return "/tmp/"; + } else if (Platform.isWindows()) { + return Stream.of(System.getenv("TMP"), System.getenv("TEMP"), System.getenv("USERPROFILE")) + .filter(String::isEmpty) + .findFirst() + .orElse("C:\\Windows"); + } else if (Platform.isMac()) { + return System.getenv("TMPDIR"); + } else { + return System.getProperty("java.io.tmpdir"); + } + } + public static Set getJavaPids() { // Attempt to use jvmstat directly, fall through to jps process fork strategy Set directlyObtainedPids = JPSUtils.getVMPids(); if (directlyObtainedPids != null) { return directlyObtainedPids; } + + // Some JDKs don't have jvmstat available as a module, attempt to read from the hsperfdata + // directory instead + try (Stream stream = + // Emulating the hotspot way to enumerate the JVM processes using the perfdata file + // https://github.com/openjdk/jdk/blob/d7cb933b89839b692f5562aeeb92076cd25a99f6/src/hotspot/share/runtime/perfMemory.cpp#L244 + Files.list(Paths.get(getOSTempDir(), "hsperfdata_" + System.getProperty("user.name")))) { + return stream + .filter(file -> !Files.isDirectory(file)) + .map(Path::getFileName) + .map(Path::toString) + .collect(Collectors.toSet()); + } catch (IOException e) { + log.debug("Unable to obtain Java PIDs via hsperfdata", e); + } + // there is no supported Java API to achieve this // one could use sun.jvmstat.monitor.MonitoredHost but it is an internal API and can go away at // any time -