RFR: 8225763: Inflater and Deflater should implement AutoCloseable [v3]
Stuart Marks
smarks at openjdk.org
Mon Jun 17 06:55:12 UTC 2024
On Sun, 16 Jun 2024 06:36:00 GMT, Jaikiran Pai <jpai at openjdk.org> wrote:
>> Can I please get a review of this enhancement which proposes to enhance `java.util.zip.Deflater/Inflater` classes to now implement `AutoCloseable`?
>>
>> The actual work for this was done a few years back when we discussed the proposed approaches and then I raised a RFR. At that time I couldn't take this to completion. The current changes in this PR involve the implementation that was discussed at that time and also have implemented the review suggestions from that time. Here are those previous discussions and reviews:
>>
>> https://mail.openjdk.org/pipermail/core-libs-dev/2019-June/061079.html
>> https://mail.openjdk.org/pipermail/core-libs-dev/2019-July/061177.html
>> https://mail.openjdk.org/pipermail/core-libs-dev/2019-July/061229.html
>>
>> To summarize those discussions, we had concluded that:
>> - `Deflater` and `Inflater` will implement the `AutoCloseable` interface
>> - In the `close()` implementation we will invoke the `end()` method (`end()` can be potentially overridden by subclasses).
>> - `close()` will be specified and implemented to be idempotent. Calling `close()` a second time or more will be a no-op.
>> - Calling `end()` and then `close()`, although uncommon, will also support idempotency and that `close()` call will be a no-op.
>> - However, calling `close()` and then `end()` will not guarantee idempotency and depending on the implementing subclass, the `end()` may throw an exception.
>>
>> New tests have been included as part of these changes and they continue to pass along with existing tests in tier1, tier2 and tier3. When I had originally added these new tests, I hadn't used junit. I can convert them to junit if that's preferable.
>>
>> I'll file a CSR shortly.
>
> Jaikiran Pai has updated the pull request incrementally with one additional commit since the last revision:
>
> Chen's suggestion - improve code comment
Hi Jai, thanks for picking this up. Several points of discussion here. Nothing fatal, but as I said in 2019 :-) just a few wrinkles to iron out. I looked mainly at Deflater, but I think the issues also all apply to Inflater too.
1) class specification
I think the class specification needs to be clearer about the positioning of end() and close(). The end() method has done the real work of "closing" since the classes were introduced. We're retrofitting them to to have a close() method that's essentially just a synonym for end(), and it's still perfectly legal for clients and subclasses to call end() instead of close(). I think we need to say that close() is present mainly to support AutoCloseable and try-with-resources.
2) end() specification
I don't think that "may throw an exception" is strong enough. Also, on these classes (not subclasses) end() is idemopotent, isn't it? If so, this should be specified. The end() specs need to say something like, closes and releases resources, etc., henceforth operations will throw an exception (which? -- see below) but that subsequent calls to end() do nothing.
3) Which exceptions on closed Deflater/Inflater?
Oddly, it doesn't seem to be specified anywhere what exceptions are thrown if operations are attempted on a closed object. And the implementation actually throws NPE??!? Ideally we should specify what exception is thrown in this circumstance, but NPE seems wrong. Maybe we want to change the behavior to throw a different exception type. IllegalStateException seems like a reasonable candidate.
4) close() specification
The 2019 discussion kind of assumed that we want close() to be idempotent. I'm not sure this is necessary. Alan said the implementation might need to be "heroic" but Peter Levart's arrangement (carried through here, apparently) isn't terribly bad. And @liach suggests more comments on this code, quite reasonably... but the comment begs the question, why do we need to avoid calling end() more than once? I'm rethinking the need for close() to be idempotent. Maybe close() should simply call end(). It would simplify the implementation and the specs -- the implSpec would simply say that it calls the end() method.
This would only be a problem if a) some arrangement of TWR ends up calling close() twice, which apparently it doesn't; b) there is a subclass; and c) the subclass's end() method is not idempotent. As far as I can tell we haven't found any example of any of these. It thus seems to me that having extra logic in close() to avoid calling end() more than once is solving a non-problem. It also fits more closely to the model of "close() is simply a synonym for end()".
-------------
PR Comment: https://git.openjdk.org/jdk/pull/19675#issuecomment-2172433871
More information about the core-libs-dev
mailing list