11package datadog .trace .util ;
22
33import datadog .trace .api .Platform ;
4- import datadog .trace .bootstrap .instrumentation .api .AgentTracer ;
5- import datadog .trace .context .TraceScope ;
64import de .thetaphi .forbiddenapis .SuppressForbidden ;
7- import java .io .BufferedReader ;
85import java .io .IOException ;
9- import java .io .InputStreamReader ;
106import java .lang .management .ManagementFactory ;
117import java .nio .file .Files ;
128import java .nio .file .Path ;
139import java .nio .file .Paths ;
1410import java .util .Collections ;
1511import java .util .Set ;
16- import java .util .concurrent .CompletableFuture ;
17- import java .util .concurrent .TimeUnit ;
1812import java .util .function .Supplier ;
1913import java .util .stream .Collectors ;
2014import java .util .stream .Stream ;
@@ -39,6 +33,7 @@ public static long getPidAsLong() {
3933 return PID_AS_LONG ;
4034 }
4135
36+ @ SuppressWarnings ("unchecked" )
4237 private static String findPid () {
4338 String pid = "" ;
4439 if (Platform .isJavaVersionAtLeast (9 )) {
@@ -123,14 +118,6 @@ private static Path getJavaProcessesDir() {
123118 }
124119
125120 public static Set <String > getJavaPids () {
126- // Attempt to use jvmstat directly, fall through to jps process fork strategy
127- Set <String > directlyObtainedPids = JPSUtils .getVMPids ();
128- if (directlyObtainedPids != null ) {
129- return directlyObtainedPids ;
130- }
131-
132- // Some JDKs don't have jvmstat available as a module, attempt to read from the hsperfdata
133- // directory instead
134121 try (Stream <Path > stream = Files .list (getJavaProcessesDir ())) {
135122 return stream
136123 .map (Path ::getFileName )
@@ -145,56 +132,22 @@ public static Set<String> getJavaPids() {
145132 if (name .isEmpty ()) {
146133 return false ;
147134 }
148- for (int i = 0 ; i < name .length (); i ++) {
149- if (!Character .isDigit (name .charAt (i ))) {
150- return false ;
151- }
135+ char c = name .charAt (0 );
136+ if (c < '0' || c > '9' ) {
137+ // Short-circuit - let's not parse as long something that is definitely not a long
138+ // number
139+ return false ;
140+ }
141+ long pid = -1 ;
142+ try {
143+ pid = Long .parseLong (name );
144+ } catch (NumberFormatException ignored ) {
152145 }
153- return true ;
146+ return pid != - 1 ;
154147 })
155148 .collect (Collectors .toSet ());
156149 } catch (IOException e ) {
157- log .debug ("Unable to obtain Java PIDs via hsperfdata" , e );
158- }
159-
160- // there is no supported Java API to achieve this
161- // one could use sun.jvmstat.monitor.MonitoredHost but it is an internal API and can go away at
162- // any time -
163- // also, no guarantee it will work with all JVMs
164- ProcessBuilder pb = new ProcessBuilder ("jps" );
165- try (TraceScope ignored = AgentTracer .get ().muteTracing ()) {
166- Process p = pb .start ();
167- // start draining the subcommand's pipes asynchronously to avoid flooding them
168- CompletableFuture <Set <String >> collecting =
169- CompletableFuture .supplyAsync (
170- () -> {
171- try (BufferedReader br =
172- new BufferedReader (new InputStreamReader (p .getInputStream ()))) {
173- return br .lines ()
174- .filter (l -> !l .contains ("jps" ))
175- .map (
176- l -> {
177- int idx = l .indexOf (' ' );
178- return l .substring (0 , idx );
179- })
180- .collect (java .util .stream .Collectors .toSet ());
181- } catch (IOException e ) {
182- log .debug ("Unable to list java processes via 'jps'" , e );
183- return Collections .emptySet ();
184- }
185- });
186- if (p .waitFor (1200 , TimeUnit .MILLISECONDS )) {
187- if (p .exitValue () == 0 ) {
188- return collecting .get ();
189- } else {
190- log .debug ("Execution of 'jps' failed with exit code {}" , p .exitValue ());
191- }
192- } else {
193- p .destroyForcibly ();
194- log .debug ("Execution of 'jps' timed out" );
195- }
196- } catch (Exception e ) {
197- log .debug ("Unable to list java processes via 'jps'" , e );
150+ log .debug ("Unable to obtain Java PIDs" , e );
198151 }
199152 return Collections .emptySet ();
200153 }
0 commit comments