44
55import com .datadog .debugger .sink .SymbolSink ;
66import datadog .instrument .utils .ClassNameTrie ;
7+ import datadog .trace .api .internal .VisibleForTesting ;
78import datadog .trace .bootstrap .debugger .DebuggerContext ;
89import datadog .trace .util .AgentTaskScheduler ;
910import datadog .trace .util .Strings ;
2829import java .util .concurrent .TimeUnit ;
2930import java .util .jar .JarEntry ;
3031import java .util .jar .JarFile ;
32+ import java .util .stream .Stream ;
3133import org .slf4j .Logger ;
3234import org .slf4j .LoggerFactory ;
3335
@@ -206,7 +208,7 @@ public void scanJar(
206208 scanDirectory (jarPath , alreadyScannedJars , baos , buffer , symDBReport );
207209 } else {
208210 try {
209- try (JarFile jarFile = new JarFile (jarPathFile )) {
211+ try (JarFile jarFile = openJarFile (jarPathFile )) {
210212 jarFile .stream ()
211213 .filter (jarEntry -> jarEntry .getName ().endsWith (".class" ))
212214 .filter (
@@ -225,14 +227,19 @@ public void scanJar(
225227 alreadyScannedJars .add (jarPath .toString ());
226228 }
227229
230+ @ VisibleForTesting
231+ JarFile openJarFile (File file ) throws IOException {
232+ return new JarFile (file );
233+ }
234+
228235 private void scanDirectory (
229236 Path jarPath ,
230237 Set <String > alreadyScannedJars ,
231238 ByteArrayOutputStream baos ,
232239 byte [] buffer ,
233240 SymDBReport symDBReport ) {
234- try {
235- Files . walk ( jarPath )
241+ try ( Stream < Path > paths = Files . walk ( jarPath )) {
242+ paths
236243 // explicitly no follow links walking the directory to avoid cycles
237244 .filter (path -> Files .isRegularFile (path , LinkOption .NOFOLLOW_LINKS ))
238245 .filter (path -> path .toString ().endsWith (".class" ))
@@ -276,11 +283,14 @@ private void parseJarEntry(
276283 byte [] buffer ) {
277284 LOGGER .debug ("parsing jarEntry class: {}" , jarEntry .getName ());
278285 try {
279- InputStream inputStream = jarFile .getInputStream (jarEntry );
280- int readBytes ;
281- baos .reset ();
282- while ((readBytes = inputStream .read (buffer )) != -1 ) {
283- baos .write (buffer , 0 , readBytes );
286+ // must be closed so the JarFile returns its Inflater to the cache instead of allocating a
287+ // new native zlib context per entry
288+ try (InputStream inputStream = jarFile .getInputStream (jarEntry )) {
289+ int readBytes ;
290+ baos .reset ();
291+ while ((readBytes = inputStream .read (buffer )) != -1 ) {
292+ baos .write (buffer , 0 , readBytes );
293+ }
284294 }
285295 parseClass (symDBReport , jarEntry .getName (), baos .toByteArray (), jarPath .toString ());
286296 } catch (IOException ex ) {
0 commit comments