Some Classes with a public void close() don't implement AutoCloseable

Remi Forax forax at univ-mlv.fr
Sun Apr 19 17:24:14 UTC 2020


TWR really means try-with-IO-resources.

Java IO objects (InputStream/Channel etc) uses a 2 transitions model instead of a 3 transitions model, something i've always found smart.
Instead of new -> open -> close, it's new/open -> close. The object creation and the opening of the resource are concomitant.
Obviously you have exception (URLConnection) and all the buffered streams [0] but the idea is that the resource object is first allocated and in the constructor the resource is allocated so you have no issue with OutOfMemoryError.

TWR is tailored to follow that model, that why it's not a good construct for locks (new -> lock -> unlock) or any objects that have a 3 transition model.

If a some point we want to introduce a construct for the 3 transition model, instead of trying to patch TWR, it may better to consider it as its own construct and see it can be retrofit it as TWR in a second step.

regards,
Rémi

[0] java.nio.file.Files alswo introduce in Java 7 provides methods carefully designed to create and open buffered streams in one call.

----- Mail original -----
> De: "John Rose" <john.r.rose at oracle.com>
> À: "Eric Vergnaud" <eric.vergnaud at wanadoo.fr>, "Florian Weimer" <fw at deneb.enyo.de>, "Brian Goetz"
> <Brian.Goetz at oracle.com>
> Cc: "discuss" <discuss at openjdk.java.net>
> Envoyé: Samedi 18 Avril 2020 20:27:52
> Objet: Re: Some Classes with a public void close() don't implement AutoCloseable

> On Apr 18, 2020, at 8:54 AM, Eric Vergnaud <eric.vergnaud at wanadoo.fr> wrote:
>> 
>> If TWR accepted both AutoOpenable and AutoCloseable, then there would be no
>> break the current behavior, but it would become possible to implement the now
>> desired behavior?
>> (appreciate this would require some additional thinking for existing
>> AutoCloseable classes)
> 
> Yes, that’s the opening motion of a long and searching conversation. Getting it
> wrong leads to Brian’s “epicyclical bags”, turning a simply-flawed design into
> a complexly-flawed one. Getting it right is what Mark calls “selective
> sedimentation”, that carefully matches good ideas from other languages to
> Java’s peculiarities without breaking backward compatibility. It takes much
> time and effort to seal these deals.
> 
> FTR my precedents here are C++ RAII and Scheme’s dynamic-wind, which are only
> starting points. I haven’t looked closely at Python or Mesa or Modula3, which
> are probably relevant, since they are system-building languages with objects
> and some CF abstraction.  Common Lisp and Smalltalk make the same compromises
> as today’s TWR in Java. (Sorry; never heard of Prompto, but I do know that with
> care you can build compositional open/close resources out of objects.)
> 
> One hard part is coaxing Java‘s object-oriented types to host yet another
> control flow abstraction, even a small one; AutoCloseable is a very carefully
> balanced OO design (look at its exception handling).  It’s very hard to write
> CF abstractions so they compose in the OO style. (Yes, it’s easy to propose
> hooks as we are discussing but hard to make them hang together cleanly.) Just
> pointing out a precedent, or a proposed “hook”, or a surprising mis-feature, as
> we are doing here, is about 2% of the effort.
> 
> Brian is right to mention for-each, which is an even trickier problem. There are
> uncertain futures which may be relevant to TWR extensions:  Loom’s
> continuations are currently under the covers, but might need a way to interact
> with re-entrant blocks (that’s part of dynamic-wind). We know that Java may
> need new abstraction tools to model parts of Java’s built-in language, to unify
> primitives with values—it is possible that these tools, once built, may provide
> the best approach to some TWR 2.0 which is decisively better, rather than a
> bolt-on.  Or, maybe after running some corpus experiments and getting several
> architect types on EGs to think for a few weeks about it, something like what
> we are discussing here might turn out to be an economical move.
> 
> The actual hook I’m suggesting here is not the interesting part of TWR’s
> technical debt to me—such hooks were surely discussed originally and rejected
> for reasons Brian suggested.  The interesting part (to me) is the practical
> results of the deliberate simplification of TWR, which I have ventured to call
> (in hindsight *only*) a mis-feature, because (only in hindsight) we have
> realized that it doesn’t sufficiently encourage exactly-correct placement of
> the opening bracket that TWR will close, *in a minority of use cases*.
> Normally we don’t design for a minority of use cases, but we might reconsider
> if those use cases are not otherwise controllable by the user.
> 
> What’s the minority use case here?  Well, it’s the need (by some users) to
> clearly and exactly separate argument checking and setup (including low-level
> effects on JVM stack and heap!) from the actual commit-to-open (in some lock
> abstractions), leading to a hard-to-solve “lost close” problem that was only a
> vague theory when TWR was designed.  Now we are clumsily patching around some
> of these problems at the JVM level (JDK-8046936) and I’m beginning to think
> there’s a more comprehensive and reliable solution that involves help from the
> user, via an amendment to TWR.
> 
> Anyway, this conversation may elucidate some technical debt or investment
> opportunity concerning TWR but executing on it (even with a small “tweak”) will
> require time and effort, far outside the scope of an email thread.  Most of us
> know this, but it bears repeating, because it’s easy to forget in the heat of
> the creative moment.
> 
> A good exposition of how small changes can be made to Java is this by Joe Darcy
> for Project Coin:
>   https://wiki.openjdk.java.net/display/Coin/Main
> 
> HTH!
> 
> — John


More information about the discuss mailing list