4
4
import static com .datadog .debugger .util .ClassFileHelper .stripPackagePath ;
5
5
6
6
import com .datadog .debugger .util .ClassFileHelper ;
7
+ import datadog .trace .util .AgentTaskScheduler ;
7
8
import java .lang .instrument .ClassFileTransformer ;
8
9
import java .lang .instrument .IllegalClassFormatException ;
9
10
import 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 ;
10
16
11
17
/**
12
18
* Permanent Transformer to track all Inner or Top-Level classes associated with the same SourceFile
13
19
* (String.java) Allows to get all classes that are dependent from a source file and be able to
14
20
* trigger {@link java.lang.instrument.Instrumentation#retransformClasses(Class[])} on them
15
21
*/
16
22
public class SourceFileTrackingTransformer implements ClassFileTransformer {
23
+ private static final Logger LOGGER = LoggerFactory .getLogger (SourceFileTrackingTransformer .class );
24
+
17
25
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 ;
18
29
19
30
public SourceFileTrackingTransformer (ClassesToRetransformFinder finder ) {
20
31
this .finder = finder ;
21
32
}
22
33
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
+
23
58
@ Override
24
59
public byte [] transform (
25
60
ClassLoader loader ,
@@ -31,16 +66,30 @@ public byte[] transform(
31
66
if (className == null ) {
32
67
return null ;
33
68
}
69
+ //queue.add(new SourceFileItem(className, classfileBuffer));
70
+ return null ;
71
+ }
72
+
73
+ private void registerSourceFile (String className , byte [] classfileBuffer ) {
34
74
String sourceFile = ClassFileHelper .extractSourceFile (classfileBuffer );
35
75
if (sourceFile == null ) {
36
- return null ;
76
+ return ;
37
77
}
38
78
String simpleClassName = stripPackagePath (className );
39
79
String simpleSourceFile = removeExtension (sourceFile );
40
80
if (simpleClassName .equals (simpleSourceFile )) {
41
- return null ;
81
+ return ;
42
82
}
43
83
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
+ }
45
94
}
46
95
}
0 commit comments