

Garbage collection with Automatic Resource Management in Java 7 - JavaTutorial
http://javawithswaranga.blogspot.com/2011/06/garbage-collection-with-automatic.html

======
jond3k
There's a problem with box 2. If the IOException is thrown in the stream's
constructor (FileNotFoundException) then there will be a NullPointerException
if we try to call close!

    
    
      InputStream in = null;
      try
      {
          in = new FileInputStream(new File("test.txt"));
          //do stuff with in
      }
      catch(IOException ie)
      {
          //SOPs
      }
      finally
      {
          try
          {
              if(in != null)
              {
                  in.close();
              }
          }
          catch(IOException ioe)
          {
              //can't do anything about it
          }
      }
    

This merely proves your point! :-)

~~~
yason
Thanks, I didn't realize it's this bad. My only touch base with Java has been
through Clojure.

This is just horrible. What braindead system forces you to check exceptions on
_closing_ a file handle? If everything failed silently and just produced
'null', the code would look like:

    
    
      InputStream in = new FileInputStream(new File("test.txt"));
      if (in) {
        ...dostuff...
        in.close();
      }
    

Now, that you can grasp with one _glance_. I'll trade the ability to write
something like that with having to use malloc()/free() any day.

~~~
barrkel
Silent failure doesn't carry information about how the thing failed: did the
file not exist, was it not accessible because of security, was there a failure
on the underlying device or file system?

How is the user supposed to figure out what went wrong with the program if the
program can't even convey to the user what went wrong?

Complex problems have lots of simple wrong answers.

(Your "solution" also suggests nothing about how "in.close()" is going to get
called if "...dostuff..." itself throws an exception.)

------
JavaFirehose
It's a much needed cleanup of something that's always resulted in clutter in
my code. C# has had this feature for over a decade. Nice to see Java adding
this since I have a lot of Java code to maintain. Like a lot of Java devs
we're switching over to Scala for new projects and using vanilla Java for
legacy code. Automatic resource management can be implemented trivially in
Scala without the need for a new language feature to support it. Structural
subtyping is awesome!

~~~
oconnor0
How does structural subtyping help you implement automatic resource
management?

~~~
JavaFirehose
I can define a resource management method which accepts any object which
belongs to a class that provides a close method irrespective of whether that
class implements close as part of an an interface or not.

~~~
sixcorners
(I had another comment here but I figured out the answer.)

lombok's @Cleanup will close anything, interface or not.

~~~
grepgrep
I took a look at lombok and it's pretty obvious from the way cleanup method
names can be passed as strings that's it's using reflection. It's a bit of a
nasty hack, but it works.

~~~
sixcorners
It fiddles with the AST during compilation. No reflection.

~~~
thebluesky
Sounds like it's trying to add structural subtyping via the back door.

------
Robin_Message
Offtopic: In the past ~week Blogger blogs have started opening on the comments
section rather than the top of the page. Anyone else?

------
jon6
This is a welcome addition to java but I wish they had chosen a slightly
different syntax. My main gripe is that its not clear what the lexical scoping
rules are. Most likely the variable declared in the try is only available in
the body of the try, not in the catch but its an extra thing to know. As
opposed to

    
    
       InputStream in;
       try(in = new FileInputStream()){
          ...
       } catch (...){
          ...
       }
    

Now there are no new lexical scoping rules to understand. A lesser point is
that I find the try(x = e) syntax ugly. It reminds me of the C-ism where a
variable is set and tested in an if statement.

    
    
       if (x = getline()){
         ...
       }
    

Control flow and side effects should not be mixed, IMO.

------
yason
If Java had stack allocated objects there would be no need for new interfaces
nor new syntax.

~~~
barrkel
It's not that simple. It doesn't just apply to stack allocated objects;
resource ownership (in the sense of being responsible for "closing" the
resource when you are yourself "closed") may and often does logically form a
tree throughout the heap, and doesn't easily flatten to stack allocated
objects without going further into allocating objects inline in other objects.

And when you introduce that, you have a problem of dealing with the difference
between references to these inline objects: possibly on the stack or the heap,
free-standing or embedded. If a reference escapes and outlives the lifetime of
the object, you've created a potential dangling pointer, whereas in the normal
Java or C# implementation you have at worst a semantic problem of having
leaked a reference to a "closed" or disposed object. The GC won't collect it,
but any operations on it will and should fail.

If you try and deal with this in the C++ way, you'll end up with far more
confusion over objects passed around by reference, and objects passed around
by value. Instead of the mechanism of passing being encoded by the type, it
would be part of the control flow, and it would be easy to get into situations
where you're working with a reference to a copy that was passed by value, and
think you have a reference to the original; this is already a problem in C# to
the degree that it is not recommended to create mutable value types.

TL;DR: what you suggest would create far more problems than it solves.

------
tbrownaw
Great, now it just needs a way to prevent you from forgetting to use that...

------
drstrangevibes
its nice but the issue for me is that it will be backwards compatible so the
preJRE7 way of managing IO resources is also included , this means an even
more bloated java api :-(

~~~
grepgrep
I think the only thing that was added to the API was a single interface called
Closeable. Adding 1 interface to a library is hardly bloat. The change is
essentially language support for a common syntax for resource management, not
a new API.

