44import static com .datadog .debugger .util .ClassFileHelper .stripPackagePath ;
55
66import com .datadog .debugger .util .ClassFileHelper ;
7+ import datadog .trace .util .AgentTaskScheduler ;
78import java .lang .instrument .ClassFileTransformer ;
89import java .lang .instrument .IllegalClassFormatException ;
910import java .security .ProtectionDomain ;
11+ import java .util .Queue ;
12+ import java .util .concurrent .ConcurrentLinkedQueue ;
13+ import java .util .concurrent .TimeUnit ;
14+ import org .slf4j .Logger ;
15+ import org .slf4j .LoggerFactory ;
1016
1117/**
1218 * Permanent Transformer to track all Inner or Top-Level classes associated with the same SourceFile
1319 * (String.java) Allows to get all classes that are dependent from a source file and be able to
1420 * trigger {@link java.lang.instrument.Instrumentation#retransformClasses(Class[])} on them
1521 */
1622public class SourceFileTrackingTransformer implements ClassFileTransformer {
23+ private static final Logger LOGGER = LoggerFactory .getLogger (SourceFileTrackingTransformer .class );
24+
1725 private final ClassesToRetransformFinder finder ;
26+ private final Queue <SourceFileItem > queue = new ConcurrentLinkedQueue <>();
27+ private final AgentTaskScheduler scheduler = AgentTaskScheduler .INSTANCE ;
28+ private AgentTaskScheduler .Scheduled <Runnable > scheduled ;
1829
1930 public SourceFileTrackingTransformer (ClassesToRetransformFinder finder ) {
2031 this .finder = finder ;
2132 }
2233
34+ public void start () {
35+ scheduled = scheduler .scheduleAtFixedRate (this ::flush , 0 , 1 , TimeUnit .SECONDS );
36+ }
37+
38+ public void stop () {
39+ if (scheduled != null ) {
40+ scheduled .cancel ();
41+ }
42+ }
43+
44+ void flush () {
45+ if (queue .isEmpty ()) {
46+ return ;
47+ }
48+ int size = queue .size ();
49+ long start = System .nanoTime ();
50+ SourceFileItem item ;
51+ while ((item = queue .poll ()) != null ) {
52+ registerSourceFile (item .className , item .classfileBuffer );
53+ }
54+ LOGGER .debug (
55+ "flushing {} source file items in {}ms" , size , (System .nanoTime () - start ) / 1_000_000 );
56+ }
57+
2358 @ Override
2459 public byte [] transform (
2560 ClassLoader loader ,
@@ -31,16 +66,30 @@ public byte[] transform(
3166 if (className == null ) {
3267 return null ;
3368 }
69+ queue .add (new SourceFileItem (className , classfileBuffer ));
70+ return null ;
71+ }
72+
73+ private void registerSourceFile (String className , byte [] classfileBuffer ) {
3474 String sourceFile = ClassFileHelper .extractSourceFile (classfileBuffer );
3575 if (sourceFile == null ) {
36- return null ;
76+ return ;
3777 }
3878 String simpleClassName = stripPackagePath (className );
3979 String simpleSourceFile = removeExtension (sourceFile );
4080 if (simpleClassName .equals (simpleSourceFile )) {
41- return null ;
81+ return ;
4282 }
4383 finder .register (sourceFile , className );
44- return null ;
84+ }
85+
86+ private static class SourceFileItem {
87+ final String className ;
88+ final byte [] classfileBuffer ;
89+
90+ public SourceFileItem (String className , byte [] classfileBuffer ) {
91+ this .className = className ;
92+ this .classfileBuffer = classfileBuffer ;
93+ }
4594 }
4695}
0 commit comments