MayHoldCloseableResource vs AutoCloseable

Brian Goetz brian.goetz at
Mon Jul 8 07:54:57 PDT 2013

This was all extensively hashed out on the EG list, you should read the 

The difference is in the presumption.  An AC object is *assumed to* 
require closing, unless you can demonstrate a reason why it does not 
require closing (e.g., ByteArrayInputStream holds no GC-resistent 
resources and its close() method does nothing.)

A MHCR object should be presumed *not to* require closing, unless you 
know that it does (e.g., an IO-backed stream.)

Static analysis tools are one audience for this distinction, but there's 
another important one: the brains of people who read code.

Not closing something that holds a file handle is a big problem, but at 
the same time, we don't want to ask people to write:

int sum =


int sum;
try (IntStream s =
                        .map(...)) {
     sum = s.sum();

just because list *might* hold a file handle.

On the other hand, we want streams to be closeable, because if they do 
hold resources, we want for derived streams (like concat(a, b)) to be 
able to ass the close message to their constituent components.

So the problem here is "must implement a close mechanism, but 99% of the 
time, users should pretend they don't and just go on with normal 
coding."  And if they're going to implement a close mechanism, NOT 
implementing AC is dumb.

The reality is there are lots of places where we rely on users to know 
stuff that can't be determined from the static type system.  For example:

  - This object is thread-confined (or thread-safe), so I can access its 
state without additional synchronization
  - This object is immutable, so I can freely share it with other code 
without copying it

We routinely rely on the user to know when certain things are safe, and 
very often the user does know these things.  The same is true with "does 
this stream hold a GC-resistent resource like a file handle."  Because 
streams are designed to be created and traversed in the same expression, 
most of the time, the user already knows with certainty.  In those cases 
where a framework has to manipulate streams (like Stream.concat) and 
therefore has to operate in generality, it can take the conservative 
route and assume that closing is needed.

You can consider this as a loose end from Coin, where AC only considered 
the case where it was reasonable to presume that failure to close was an 
error.  The case where closing is supported but not expected was not 
handled by AC.  MHCR attempts to address that.  Is it beautiful? 
Certainly not.  But, as Doug said, it "provides something better than 
any other related schemes I know."  If the name weren't so clunky, I 
daresay you might not have even noticed.

On 7/8/2013 10:20 AM, Paul Benedict wrote:
> What are the semantic differences between these two interfaces? I come away
> with no programming difference (i.e., you will always need to close the
> stream because it *could* hold a resource); but it's more of a hint to IDEs
> not to display a "resource leak" warning if try-with-resources is not used.
> Am I correct? The only reason I ask is because it seems this interface can
> be done without. I think it would be much more palatable to use just the
> annotation only rather than the sub-interface.
> Paul

More information about the lambda-dev mailing list