The Artima Developer Community
Sponsored Link

Articles Forum
From JavaOne 2009: On Trust and Types

30 replies on 3 pages. Most recent reply: Oct 6, 2009 1:43 PM by art src

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 30 replies on 3 pages [ 1 2 3 | » ]
Frank Sommers

Posts: 2642
Nickname: fsommers
Registered: Jan, 2002

From JavaOne 2009: On Trust and Types Posted: Jun 11, 2009 9:00 AM
Reply to this message Reply
Advertisement
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 Mueller

Posts: 18
Nickname: thomasm
Registered: Jan, 2009

Re: From JavaOne 2009: On Trust and Types Posted: Jun 11, 2009 11:37 PM
Reply to this message Reply
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 Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: From JavaOne 2009: On Trust and Types Posted: Jun 12, 2009 8:26 AM
Reply to this message Reply
> 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 Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: From JavaOne 2009: On Trust and Types Posted: Jun 12, 2009 8:47 AM
Reply to this message Reply
> 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 Sommers

Posts: 2642
Nickname: fsommers
Registered: Jan, 2002

Re: From JavaOne 2009: On Trust and Types Posted: Jun 12, 2009 10:04 AM
Reply to this message Reply
> 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 Mueller

Posts: 18
Nickname: thomasm
Registered: Jan, 2009

Re: From JavaOne 2009: On Trust and Types Posted: Jun 12, 2009 12:59 PM
Reply to this message Reply
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 Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: From JavaOne 2009: On Trust and Types Posted: Jun 12, 2009 1:25 PM
Reply to this message Reply
> '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 Mueller

Posts: 18
Nickname: thomasm
Registered: Jan, 2009

Re: From JavaOne 2009: On Trust and Types Posted: Jun 12, 2009 10:41 PM
Reply to this message Reply
> '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 Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: From JavaOne 2009: On Trust and Types Posted: Jun 13, 2009 5:43 PM
Reply to this message Reply
> 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 Thornton

Posts: 275
Nickname: mthornton
Registered: Oct, 2005

Re: From JavaOne 2009: On Trust and Types Posted: Jun 14, 2009 4:47 AM
Reply to this message Reply
> 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 Mueller

Posts: 18
Nickname: thomasm
Registered: Jan, 2009

Re: From JavaOne 2009: On Trust and Types Posted: Jun 14, 2009 7:34 AM
Reply to this message Reply
> 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 Thornton

Posts: 275
Nickname: mthornton
Registered: Oct, 2005

Re: From JavaOne 2009: On Trust and Types Posted: Jun 14, 2009 7:57 AM
Reply to this message Reply
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 Mueller

Posts: 18
Nickname: thomasm
Registered: Jan, 2009

Re: From JavaOne 2009: On Trust and Types Posted: Jun 14, 2009 8:34 AM
Reply to this message Reply
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 Mueller

Posts: 18
Nickname: thomasm
Registered: Jan, 2009

Re: From JavaOne 2009: On Trust and Types Posted: Jun 14, 2009 9:13 AM
Reply to this message Reply
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 Conrad

Posts: 307
Nickname: miata71
Registered: Mar, 2006

Re: From JavaOne 2009: On Trust and Types Posted: Jun 14, 2009 1:43 PM
Reply to this message Reply
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.

Flat View: This topic has 30 replies on 3 pages [ 1  2  3 | » ]
Topic: JetBrains' Dmitry Jemerov on IntelliJ 8, Flex, and Scala Previous Topic   Next Topic Topic: Time is the New Memory

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use