Article Discussion
From JavaOne 2009: On Trust and Types
Summary: The JVM's promise of write once, run anywhere works most of the time. But it can also make programmers complacent about cases where the WORA promise fails, says Gwyn Fisher, CTO of Klocwork, maker of the eponymous code analysis tool. One such case is resource management, where the JVM's latent garbage collector necessitates that developers think about the machine behind the VM. In this interview with Artima, Fisher describes cases where well-known Java APIs work differently based on deployment platform, and how well-defined type systems can make resource management more reliable:
31 posts on 3 pages.      
« Previous 1 2 3 Next »
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: October 6, 2009 0:43 PM by
Frank
Posts: 135 / Nickname: fsommers / Registered: January 19, 2002 7:24 AM
From JavaOne 2009: On Trust and Types
June 11, 2009 8:00 AM      
In this interview with Artima, Gwyn Fisher, CEO of Klocwork, describes cases where well-known Java APIs work differently based on deployment platform, and how well-defined type systems can make resource management more reliable:

http://www.artima.com/lejava/articles/javaone2009_gwyn_fisher.html

What do you think of the notion that types can help you improve trust in APIs?
Thomas
Posts: 12 / Nickname: thomasm / Registered: January 27, 2009 1:41 AM
Re: From JavaOne 2009: On Trust and Types
June 11, 2009 10:37 PM      
There is a workaround to auto-close resources:
InputStream in = ...
synchronized (closeLater(in)) {
  // reading
}

This is guaranteed to close the input stream 1 second after it is no longer used (synchronized). The closeLater method looks like this:
static InputStream closeLater(final InputStream in) {
  new Thread(new Runnable() {
    public void run() {
      try {
        synchronized (in) {
          in.wait(1000);
          in.close();
        }
      } catch (Exception e) { }
    }
  }).start();
  return in;
}

I know it's not perfect, but it might be good enough until Java 7.
James
Posts: 128 / Nickname: watson / Registered: September 7, 2005 3:37 AM
Re: From JavaOne 2009: On Trust and Types
June 12, 2009 7:26 AM      
> There is a workaround to auto-close resources:

I prefer this approach:
class InputStreamProcessor
{
  private final InputStream stream;
 
  public InputStreamProcessor(InputStream stream)
  {
    this.stream = stream;
  }
 
  void process(StreamReceiver receiver) throws IOException
  {
    byte[] buffer = new byte[1024];
 
    try {
      do {
        int read = stream.read(buffer);
 
        if (!receiver(buffer, read) return;
      } while (read >= 0);
    } finally {
      stream.close();
    }
  }
 
  public interface Receiver
  {
    boolean process(byte[], int len);
  }
}


This is a simplified example but it should give the basic idea. If more APIs were developed in this style, I think this wouldn't be such a big issue.

> but it might be good enough until Java 7.

What's happening in Java 7 to change this? Sorry, I haven't been following this for a while. Closures would help with the above but is there something else you are talking about here?
James
Posts: 128 / Nickname: watson / Registered: September 7, 2005 3:37 AM
Re: From JavaOne 2009: On Trust and Types
June 12, 2009 7:47 AM      
> What do you think of the notion that types can help you
> improve trust in APIs?

OK, I'll just go ahead and confess that I don't know how types would do that. It's actually a little confusing to me because Java has a notion of 'type' that I don't think is the same as what is being discussed here.

P.S. I hate to do the grammar police thing but I see this error so often and I find it to be really annoying. I normally don't say anything but this is ostensibly an edited article. The phrase "you loose track", the word you want here is 'lose' not 'loose'. I know it's confusing because 'lose' rhymes with 'choose', but there's a big difference in meaning between the words.
Frank
Posts: 135 / Nickname: fsommers / Registered: January 19, 2002 7:24 AM
Re: From JavaOne 2009: On Trust and Types
June 12, 2009 9:04 AM      
> P.S. I hate to do the grammar police thing but I see this
> error so often and I find it to be really annoying. I
> normally don't say anything but this is ostensibly an
> edited article. The phrase "you loose track", the word
> you want here is 'lose' not 'loose'. I know it's
> confusing because 'lose' rhymes with 'choose', but there's
> a big difference in meaning between the words.

Thanks! That was a typo. We just fixed it.
Thomas
Posts: 12 / Nickname: thomasm / Registered: January 27, 2009 1:41 AM
Re: From JavaOne 2009: On Trust and Types
June 12, 2009 11:59 AM      
Hi James,

Your solution is a 'closure'. Too bad this pattern is hard to use in Java: 'final' everywhere, and calling the method is complicated.

'My' solution is simpler to use, unfortunately it closes the stream a little bit too late (the code I posted up to 1 second, but using some tricks it could be reduced to a few milliseconds on average). My solution can still be improved.

> What's happening in Java 7 to change this?

See Project Coin - http://openjdk.java.net/projects/coin/ - specially Automatic Resource Management, V.2: http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001481.html - it's not accepted yet, but I hope it will.
James
Posts: 128 / Nickname: watson / Registered: September 7, 2005 3:37 AM
Re: From JavaOne 2009: On Trust and Types
June 12, 2009 0:25 PM      
> 'My' solution is simpler to use

I guess I'm not really seeing that. I don't see why it's any easier to put synchronized block around your read loop than to put a try catch block around your read loop.

I use the technique I posted above for database access and it can be akward and verbose at times but it's definitely worth the payoff.
Thomas
Posts: 12 / Nickname: thomasm / Registered: January 27, 2009 1:41 AM
Re: From JavaOne 2009: On Trust and Types
June 12, 2009 9:41 PM      
> 'My' solution is simpler to use:

synchronized(closeLater(in)) {
..
}
than try...catch:

try {
..
} finally {
try {
in.close();
} catch (IOException e) {
// ignore
}
}

The problem if your solution is that you can only access variables outside the block if they are declared final.
James
Posts: 128 / Nickname: watson / Registered: September 7, 2005 3:37 AM
Re: From JavaOne 2009: On Trust and Types
June 13, 2009 4:43 PM      
> The problem if your solution is that you can only access
> variables outside the block if they are declared final.

That's true if you use an anonymous inner class and the variables are local. In that case, it generally isn't a big deal. I usually end adding items to a list or calling some other method on my enclosing class so it doesn't matter. In the cases where I need to write once to a local, I just declare it like so:
int[] out = {0};

Pretty, no, but it works just fine.

The other thing about using the closure-style or pseudo-functional style is that you it's easy to write reusable classes to pass into these functions or write inner classes or nested classes. I readily admit that this is verbose but it works really well in practice.

The problem I see with using threads and synchronized blocks is that you could end up creating lots of little threads (and negatively impacting performance.) One thing you might consider for this is using a single-threaded Executor instead of spawning a thread for each call.
Mark
Posts: 48 / Nickname: mthornton / Registered: October 16, 2005 11:22 PM
Re: From JavaOne 2009: On Trust and Types
June 14, 2009 3:47 AM      
> There is a workaround to auto-close resources:
> InputStream in = ...
> synchronized (closeLater(in)) {
>   // reading
> }


It is at least theoretically possible that your main thread won't execute the synchronized statement until after the thread started by closeLater has completed. With a 1000ms wait this is unlikely, but not quite impossible.
Thomas
Posts: 12 / Nickname: thomasm / Registered: January 27, 2009 1:41 AM
Re: From JavaOne 2009: On Trust and Types
June 14, 2009 6:34 AM      
> possible that your main thread won't execute ... until after the thread started by closeLater has completed.

True. A better workaround is:
static void closeLater(final InputStream in, final Object sync) {
    if (!Thread.holdsLock(sync)) {
        throw new IllegalStateException("must first synchronize on " + sync);
    }
    Thread t = new Thread(new Runnable() {
        public void run() {
            try { synchronized (sync) { in.close(); } } catch (Exception e) { }
        }
    });
    t.start();
    while (t.getState() != State.BLOCKED) Thread.yield();
}

Usage is a bit different, one example is:
synchronized void test() throws Exception {
    InputStream in = new ByteArrayInputStream(new byte[0]);
    closeLater(in, this);
    // read...
}

It is a bit more complicated to understand.
Mark
Posts: 48 / Nickname: mthornton / Registered: October 16, 2005 11:22 PM
Re: From JavaOne 2009: On Trust and Types
June 14, 2009 6:57 AM      
I'd prefer a solution like this
CloseableStack.Mark mark = CloseableStack.mark()
try {
  InputStream in = CloseableStack.open(new FileInputStream(...));
  // ... read, possibly open more streams
} finally {
   mark.close();
}


CloseableStack would manage thread local stacks. CloseableStack.Mark.close() would close all objects opened since its creation (and not throw any checked exceptions). While this still requires one finally clause it isn't as complex as that usually required.
Thomas
Posts: 12 / Nickname: thomasm / Registered: January 27, 2009 1:41 AM
Re: From JavaOne 2009: On Trust and Types
June 14, 2009 7:34 AM      
Another option is to use closeQuietly as in:
http://commons.apache.org/dbutils/apidocs/org/apache/commons/dbutils/DbUtils.html
If you implement those methods yourself, you might want to log errors when closing.
Thomas
Posts: 12 / Nickname: thomasm / Registered: January 27, 2009 1:41 AM
Re: From JavaOne 2009: On Trust and Types
June 14, 2009 8:13 AM      
The advantage of the 'synchronized solution' is that you can actually enforce the 'correct' usage. Let's say you wrote a library with a method "public InputStream getStream()". There is no way to enforce that the caller of the method calls in.close(). If you change the API to "public InputStream getStream(Object sync)" and use my solution, then the caller doesn't have to close the stream (he still can), but he has to use a synchronized block - your library can enforce this using "if (!Thread.holdsLock(in)) throw ...". Your library will close the stream if the caller forgot (shortly after the synchronized block ends).
Morgan
Posts: 37 / Nickname: miata71 / Registered: March 29, 2006 6:09 AM
Re: From JavaOne 2009: On Trust and Types
June 14, 2009 0:43 PM      
I like Mark's idea, cause it nicely handles where you have multiple streams to open/close. Reminds me of an old Amiga option to remember all the mallocs you were making, then you could close them all i one call.

Does CloseableStack code exist, or it is a dream? I tried (briefly) writing code to do similar but got stuck.
31 posts on 3 pages.
« Previous 1 2 3 Next »