Request for Review: 7094995: test/java/util/zip/ZipFile/ClearStaleZipFileInputStreams.java causes continuous GC in agentvm mode

Neil Richards neil.richards at ngmr.net
Thu Nov 24 11:15:28 UTC 2011


On Thu, 2011-11-24 at 11:22 +1000, David Holmes wrote:
> Hi Joe,
> 
> On 24/11/2011 2:33 AM, Joe Darcy wrote:
> > On 11/22/2011 9:57 PM, David Holmes wrote:
> >> On 22/11/2011 9:51 PM, Neil Richards wrote:
> >>> I've also converted the testcase's use of ZipFile, ZipOutputStream&
> >>> FileOutputStream to use ARM (for greater clarity).
> >>
> >> I think proper use of ARM requires that this:
> >>
> >> 66 try (ZipOutputStream zos =
> >> 67 new ZipOutputStream(new FileOutputStream(tempZipFile))) {
> >>
> >> be written as:
> >>
> >> try (FileOutputStream fos = new FileOutputStream(tempZipFile);
> >> ZipOutputStream zos = new ZipOutputStream(fos)) {
> >>
> >
> > The more conservative approach is to define one resource variable per
> > logical resource even if the one resource is "wrapped" by the second
> > one, as in the second example. This does close the small window of
> > vulnerability between when the first constructor call ends and the
> > second one completes. However, if that pattern is used, it is important
> > for the close method of the inner resource to be idempotent, as required
> > by the java.io.Closeable type but *not* required by
> > java.lang.AutoCloseable.
> 
> Sorry but I couldn't quite tell what you were recommending there. Is the 
> original code or my change the preferred approach? As I understood it 
> the original code would not close the FileOutputStream if the 
> ZipOutputStream constructor threw an exception.
> 
> Thanks,
> David

In this instance, I think separating the allocations out into separate
statements in the ARM's try is fine, because both FileOutputStream and
ZipOutputStream are Closeable, and therefore have idempotent [1] close()
methods. (They're obviously also both AutoCloseable, to be used by ARM
in the first place).

-----

Consider, however, if FileOutputStream were not Closeable, and therefore
didn't guarantee the idempotency of its close(). 

(It might then do something like throw an Exception if close() is called
for a second time.)

Then the decision to have it auto-closed by ARM would hinge upon whether
the call to ZipOutputStream's close() causes a close() call to be made
to the (File)OutputStream it holds. 

If it does, one would not want to use ARM to (also) call the
(non-Closeable) FileOutputStream's close(), as it would run the risk of
seeing non-idempotent behaviour (eg. an Exception thrown).

-----

However, coming back to reality, both objects _are_ Closeable, and so
_do_ have idempotent close() methods.

Therefore it's both safe to have them both handled by ARM, and (I'd
argue) clearer to do so, as it's then clear both objects _do_ get
closed, without having to consider the finer details of
ZipOutputStream.close().

I believe Joe was defining the considerations needed when making such a
modification in the general case.

(Joe, please correct me if I misinterpreted this).

-----

If I'm correct on this, then I think my suggested change [2] is still
good to go.
Please speak up if there remain issues with it.

Regards, Neil

[1] http://en.wikipedia.org/wiki/Idempotence
(I confess, I had to look the term up)
[2] http://cr.openjdk.java.net/~ngmr/7094995/webrev.02/

-- 
Unless stated above:
IBM email: neil_richards at uk.ibm.com
IBM United Kingdom Limited - Registered in England and Wales with number 741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU




More information about the core-libs-dev mailing list