Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 389621

Summary: [compiler][resource] Resource leak warning false positive with JarOutputStream
Product: [Eclipse Project] JDT Reporter: Fabio <flsobral>
Component: CoreAssignee: Stephan Herrmann <stephan.herrmann>
Status: CLOSED WONTFIX QA Contact:
Severity: enhancement    
Priority: P3 CC: flsobral, srikanth_sankaran
Version: 4.2   
Target Milestone: 4.3 M4   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Fabio CLA 2012-09-14 11:09:29 EDT
I noticed there are a few bugs reporting problems with this warning, but I couldn't find any that matches my case.

Look at this sample code:
      String[] filesToPackage = {"file1", "file2"};
      JarOutputStream jos = new JarOutputStream(new FileOutputStream("archive.jar"));
      
      // Add files
      byte[] buffer = new byte[1024];
      for (int i=0,r; i < filesToPackage.length; i++)
      {
         jos.putNextEntry(new JarEntry(filesToPackage[i]));
         
         DeflaterOutputStream os = new DeflaterOutputStream(jos, new Deflater(Deflater.BEST_COMPRESSION, true)); // <= Resource leak warning
         FileInputStream fis = new FileInputStream(filesToPackage[i]);
         while ((r = fis.read(buffer)) > 0)
            os.write(buffer, 0, r);
         
         os.finish();
         fis.close();
//         os.close();
         jos.closeEntry();
      }
      jos.close();


Eclipse raises a "Resource leak warning" because 'os' is not explicitly closed. However, it is closed by closeEntry.
If you uncomment the 'os.close()' line the warning is fixed, but 'jos.closeEntry' fails and throws an IOException because the underlying stream is closed.
Comment 1 Stephan Herrmann CLA 2012-09-16 04:15:49 EDT
The analysis works as designed.

Changing this to an enhancement request, because we would need to add special case support for classes JarOutputStream/ZipOutputStream and possibly DeflaterOutputStream. 
I'm not at all sure, how we could capture this protocol in a meaningful way. From a first look into the classes involved it seems that new DeflaterOutputStream(jos, ...)  doesn't actually wrap the jos, but wraps a private stream that is controlled by putNextEntry and closeEntry. Analysis would need to understand that somehow jos.closeEntry does not close jos, but makes jos appear as closed from the p.o.v of the "wrapping" os, right? Opposite, the way how os.close() has side-effects on internal data of jos, makes this protocol look quite asymmetric, which makes it even harder to analyse.

This seems too complex a contract for our analysis to understand.
I'd recommend adding @SuppressWarnings("resource") just to the declaration of 'os'.

Let me know if I missed a much simpler way to specify this contract.
Comment 2 Stephan Herrmann CLA 2012-11-22 17:52:12 EST
Closing as per previous comment (and no complaints).