File tree Expand file tree Collapse file tree 8 files changed +90
-0
lines changed
agent-bootstrap/src/main/java/datadog/trace/bootstrap
agent-profiling/profiling-utils
dd-smoke-tests/profiling-integration-tests/src/test/java/datadog/smoketest
src/main_java11/java/datadog/trace/util
src/main/java/datadog/trace/util Expand file tree Collapse file tree 8 files changed +90
-0
lines changed Original file line number Diff line number Diff line change 42
42
import datadog .trace .util .AgentTaskScheduler ;
43
43
import datadog .trace .util .AgentThreadFactory .AgentThread ;
44
44
import datadog .trace .util .throwable .FatalAgentMisconfigurationError ;
45
+ import de .thetaphi .forbiddenapis .SuppressForbidden ;
45
46
import java .lang .instrument .Instrumentation ;
46
47
import java .lang .reflect .InvocationTargetException ;
47
48
import java .lang .reflect .Method ;
@@ -278,6 +279,8 @@ public static void start(
278
279
codeOriginEnabled = isFeatureEnabled (AgentFeature .CODE_ORIGIN );
279
280
agentlessLogSubmissionEnabled = isFeatureEnabled (AgentFeature .AGENTLESS_LOG_SUBMISSION );
280
281
282
+ patchJPSAccess (inst );
283
+
281
284
if (profilingEnabled ) {
282
285
if (!isOracleJDK8 ()) {
283
286
// Profiling agent startup code is written in a way to allow `startProfilingAgent` be called
@@ -407,6 +410,20 @@ private static void injectAgentArgsConfig(String agentArgs) {
407
410
}
408
411
}
409
412
413
+ @ SuppressForbidden
414
+ public static void patchJPSAccess (Instrumentation inst ) {
415
+ if (Platform .isJavaVersionAtLeast (9 )) {
416
+ // Unclear if supported for J9, may need to revisit
417
+ try {
418
+ Class .forName ("datadog.trace.util.JPMSJPSAccess" )
419
+ .getMethod ("patchModuleAccess" )
420
+ .invoke (inst );
421
+ } catch (Exception e ) {
422
+ log .warn ("Failed to patch module access for jvmstat" );
423
+ }
424
+ }
425
+ }
426
+
410
427
public static void shutdown (final boolean sync ) {
411
428
StaticEventLogger .end ("Agent" );
412
429
StaticEventLogger .stop ();
Original file line number Diff line number Diff line change 1
1
// Set properties before any plugins get loaded
2
2
ext {
3
+ // In order to patch access for jvmstat for JDK >8
4
+ minJavaVersionForTests = JavaVersion . VERSION_11
3
5
}
4
6
5
7
apply from : " $rootDir /gradle/java.gradle"
Original file line number Diff line number Diff line change @@ -507,6 +507,8 @@ void testShutdown(final TestInfo testInfo) throws Exception {
507
507
assertTrue (
508
508
targetProcess .waitFor (
509
509
duration + PROFILING_UPLOAD_TIMEOUT_SECONDS + 1 , TimeUnit .SECONDS ));
510
+ assertTrue (
511
+ checkLogLines (logFilePath , it -> it .contains ("Successfully invoked jvmstat" )));
510
512
} finally {
511
513
if (targetProcess != null ) {
512
514
targetProcess .destroyForcibly ();
Original file line number Diff line number Diff line change @@ -175,6 +175,7 @@ excludedClassesCoverage += [
175
175
" datadog.trace.util.ComparableVersion.LongItem" ,
176
176
" datadog.trace.util.ComparableVersion.StringItem" ,
177
177
" datadog.trace.util.ConcurrentEnumMap" ,
178
+ " datadog.trace.util.JPSUtils" ,
178
179
" datadog.trace.util.MethodHandles" ,
179
180
" datadog.trace.util.PidHelper" ,
180
181
" datadog.trace.util.PidHelper.Fallback" ,
Original file line number Diff line number Diff line change @@ -41,6 +41,10 @@ forbiddenApisMain {
41
41
failOnMissingClasses = false
42
42
}
43
43
44
+ forbiddenApisMain_java11 {
45
+ failOnMissingClasses = false
46
+ }
47
+
44
48
idea {
45
49
module {
46
50
jdkName = ' 11'
Original file line number Diff line number Diff line change
1
+ package datadog .trace .util ;
2
+
3
+ import java .lang .instrument .Instrumentation ;
4
+ import java .util .Collections ;
5
+ import java .util .Map ;
6
+ import java .util .Set ;
7
+
8
+ public class JPMSJPSAccess {
9
+ public static void patchModuleAccess (Instrumentation inst ) {
10
+ Module unnamedModule = JPMSJPSAccess .class .getClassLoader ().getUnnamedModule ();
11
+ Module jvmstatModule = ModuleLayer .boot ().findModule ("jdk.internal.jvmstat" ).orElse (null );
12
+
13
+ if (jvmstatModule != null ) {
14
+ Map <String , Set <Module >> extraOpens = Map .of ("sun.jvmstat.monitor" , Set .of (unnamedModule ));
15
+
16
+ // Redefine the module
17
+ inst .redefineModule (
18
+ jvmstatModule ,
19
+ Collections .emptySet (),
20
+ extraOpens ,
21
+ extraOpens ,
22
+ Collections .emptySet (),
23
+ Collections .emptyMap ());
24
+ }
25
+ }
26
+ }
Original file line number Diff line number Diff line change
1
+ package datadog .trace .util ;
2
+
3
+ import de .thetaphi .forbiddenapis .SuppressForbidden ;
4
+ import java .lang .reflect .Method ;
5
+ import java .util .HashSet ;
6
+ import java .util .List ;
7
+ import java .util .Set ;
8
+ import org .slf4j .Logger ;
9
+ import org .slf4j .LoggerFactory ;
10
+
11
+ public final class JPSUtils {
12
+ private static final Logger log = LoggerFactory .getLogger (JPSUtils .class );
13
+
14
+ @ SuppressForbidden
15
+ public static Set <String > getVMPids () {
16
+ Set <String > vmPids = new HashSet <>();
17
+ try {
18
+ Class <?> monitoredHostClass = Class .forName ("sun.jvmstat.monitor.MonitoredHost" );
19
+ Method getMonitoredHostMethod =
20
+ monitoredHostClass .getDeclaredMethod ("getMonitoredHost" , String .class );
21
+ Object vmHost = getMonitoredHostMethod .invoke (null , "localhost" );
22
+ for (Integer vmPid :
23
+ (List <Integer >) monitoredHostClass .getDeclaredMethod ("activeVms" ).invoke (vmHost )) {
24
+ vmPids .add (vmPid .toString ());
25
+ }
26
+ log .debug ("Successfully invoked jvmstat" );
27
+ } catch (Exception e ) {
28
+ log .debug ("Failed to invoke jvmstat with exception " , e );
29
+ return null ;
30
+ }
31
+ return vmPids ;
32
+ }
33
+ }
Original file line number Diff line number Diff line change @@ -65,6 +65,11 @@ private static String findPid() {
65
65
}
66
66
67
67
public static Set <String > getJavaPids () {
68
+ // Attempt to use jvmstat directly, fall through to jps process fork strategy
69
+ Set <String > directlyObtainedPids = JPSUtils .getVMPids ();
70
+ if (directlyObtainedPids != null ) {
71
+ return directlyObtainedPids ;
72
+ }
68
73
// there is no supported Java API to achieve this
69
74
// one could use sun.jvmstat.monitor.MonitoredHost but it is an internal API and can go away at
70
75
// any time -
You can’t perform that action at this time.
0 commit comments