| Summary: | [compiler][resource] Resource leak warning false positive with JarOutputStream | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Fabio <flsobral> |
| Component: | Core | Assignee: | 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: | |||
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.
Closing as per previous comment (and no complaints). |
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.