The Artima Developer Community
Sponsored Link

Articles Forum
Sources of Java Errors

29 replies on 2 pages. Most recent reply: Jun 1, 2008 7:47 AM by dark mx

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 29 replies on 2 pages [ « | 1 2 ]
Roland Pibinger

Posts: 93
Nickname: rp123
Registered: Jan, 2006

Re: Sources of Java Errors Posted: May 23, 2008 12:35 PM
Reply to this message Reply
Advertisement
> (We do use RAII with our C++ implementation. It is not
> sufficient.)

Not sufficient in what respect? RAII "merely" encapsulates and automates resource management. Of course, like any idiom it can be misunderstood and used wrongly. But I'd like to see an example where RAII is 'not sufficient' for resource management.

indranil banerjee

Posts: 38
Nickname: indranil
Registered: Nov, 2004

Re: Sources of Java Errors Posted: May 23, 2008 12:45 PM
Reply to this message Reply
>
> .. for any application so simple that reference counting
> is sufficient.
>
> (We do use RAII with our C++ implementation. It is not
> sufficient.)
>

Last I heard all VMs use reference counting in their garbage collectors. What other techniques are you referring to?

Roland Pibinger

Posts: 93
Nickname: rp123
Registered: Jan, 2006

Re: Sources of Java Errors Posted: May 23, 2008 1:58 PM
Reply to this message Reply
RAII != reference counting && RAII != GC

indranil banerjee

Posts: 38
Nickname: indranil
Registered: Nov, 2004

Re: Sources of Java Errors Posted: May 24, 2008 6:21 AM
Reply to this message Reply
> RAII != reference counting && RAII != GC

Indeed, my reply was directed at Cameron's comment which mentioned ref counting. Reference counting is a technique that is used in RAII libraries like std::shared_ptr and for garbage collection in the JVM and the CLR.

The scoping based rules like RAII + reference counting can be used powerfully to manage system resources.
Sometimes you dont need ref counts. I like to use scope guards to guarantee a function will always execute(deterministically) when a reference goes out of scope, much cleaner and more flexible than Java finally or C# using blocks.
Reference counts come into their own when you're passing handles to resources around. Sometimes even this is not enough, which is why we have weak_ptrs and WeakReferences

I would like to hear from Cameron where techniques for resource management in C++ have let him down. And how does he solve these problems in Java.

Sebastian Kübeck

Posts: 44
Nickname: sebastiank
Registered: Sep, 2005

Re: Sources of Java Errors Posted: May 24, 2008 1:11 PM
Reply to this message Reply
Before crying for new language features, why not use good old indirection? e.g.:

instead of...
<code>
CloseableResource rs = new CloseableResource();
try {
rs.foo();
} finally {
if(rs!=null) {
rs.close();
}
}
</code>

...use...

<code>
DerivedResource cr = new DerivedResource();
rs.access(new ResourceAccess() {
void access(CloseableResource rs) {
rs.foo();
}
})
</code>

The access method will do the dirty work.
Remember, it's the power of OOP that let's us improve things by <i>deriving</i> (by inheritance or encapsulation) instead of <i>changing</i> things all the time.

indranil banerjee

Posts: 38
Nickname: indranil
Registered: Nov, 2004

Re: Sources of Java Errors Posted: May 24, 2008 3:55 PM
Reply to this message Reply
> <code>
> DerivedResource cr = new DerivedResource();
> rs.access(new ResourceAccess() {
> void access(CloseableResource rs) {
> rs.foo();
> }
> })
> </code>
>

I guess I'm missing something. Where is the resource getting closed?

Sebastian Kübeck

Posts: 44
Nickname: sebastiank
Registered: Sep, 2005

Re: Sources of Java Errors Posted: May 25, 2008 2:14 AM
Reply to this message Reply
Sorry, I clicked the "post message" button to early.

the access method would look something like the this:

class DerivedResource {
//...
public void access(ResourceAccess ra) {
CloseableResource rs = null;
try {
rs = new CloseableResource();
ra.access(rs);
} finally {
if(rs != null) {
rs.close();
}
}
}
}

The whole acquiring and closing mechanism is delegated to DerivedResource now.
That way, thare's no way to forget to close the resource. Another advantage is that the boiler plate closing routine does not get duplicated over and over in the project.
If you've ever had the pleasure to fix hundreds of occurrencies of all possible variants of closing resources, you'll probably value that approach.

indranil banerjee

Posts: 38
Nickname: indranil
Registered: Nov, 2004

Re: Sources of Java Errors Posted: May 26, 2008 4:28 PM
Reply to this message Reply
Thanks Sebastian. I'm genuinely interested in the best practices for writing robust code in Java these days.
At first sight the ClosableResource version seems to involve just as much typing as the first version. I'd also like to see how this coding style works when there are multiple resources to be managed.

Could you rewrite this snippet of code using your style? Would also be interested in seeing what the RAII gang come up with.



public void test()
{
BufferedWriter writer = null;
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try
{
writer = new BufferedWriter(new FileWriter("AFile"))

conn = DriverManager.getConnection("jdbc:XXX", "USR", "PWD" );
ps = conn.prepareStatement("SELECT * FROM ATable");
rs = ps.executeQuery();
while(rs.next())
{
String data = null;
//get data from rs
writer.write(data);
}
return;
}
finally
{
if(rs != null)
rs.close();
if(ps != null)
ps.close();
if(conn != null)
conn.close();
if(writer != null)
writer.close();
}
}

Roland Pibinger

Posts: 93
Nickname: rp123
Registered: Jan, 2006

Re: Sources of Java Errors Posted: May 27, 2008 10:47 AM
Reply to this message Reply
> Could you rewrite this snippet of code using your style?
> Would also be interested in seeing what the RAII gang come
> up with.
...
 
> finally
> {
> if(rs != null)
> rs.close();
> if(ps != null)
> ps.close();
> if(conn != null)
> conn.close();
> if(writer != null)
> writer.close();
> }
> }


You often see this style in books and articles but it is not sufficient. Goetz demonstrates a proper solution with nested try/finally blocks here: http://www.ibm.com/developerworks/java/library/j-jtp03216.html (see esp. Listing 4). I would close all resources in the try block and write a special re-usable cleanup() function to be used in the finally block in case an exception occurs.

With RAII you don't have those problems because cleanup is defined once per class, not each time the resource is used. If Java had RAII you could spare 95% of all try/catch/finally blocks in the code. Lack of RAII is responsible for most of Java's proverbial verbosity.

Morgan Conrad

Posts: 307
Nickname: miata71
Registered: Mar, 2006

Re: Sources of Java Errors Posted: May 27, 2008 11:51 AM
Reply to this message Reply
For multiple closes in the finally block,

One option is to use org.apache.commons.io.IOUtils.closeQuietly(x).

It checks for x==null, and eats any exception, which makes sure that everything will get closed (if possible).

Another idea (haven't see or testing this in practice) is for the wrapper class to collect a List of java.io.Closeable, and at the end to go (backwards) through this List closing things. But not all the JDBC still implements Closeable, only the java.io stuff does.


The tricky issue is what to do if close() throws an Exception. Apache ignores it, which, IMO, is about as good as you'll get. If the preceeding IO failed, you definitely want to ignore the close() exception, cause it's semi-expected, and you want to throw the "real exception", which is something in the preceeding IO. If it's just the close() that failed, ???. I've NEVER seen this happen, and whatcha going to do about it anyway? I wrote my own IOUtils-like class (cleverly called Finally, it was a ton of methods to call in a Finally block) that returned any Exception, so the caller had the option to do something. But in practice I never checked the result, or at most just logged it and ignored it, so I started using the more standard Apache stuff.

Roland Pibinger

Posts: 93
Nickname: rp123
Registered: Jan, 2006

Re: Sources of Java Errors Posted: May 27, 2008 12:43 PM
Reply to this message Reply
> For multiple closes in the finally block,
> One option is to use
> org.apache.commons.io.IOUtils.closeQuietly(x).
>
> It checks for x==null, and eats any exception, which makes
> sure that everything will get closed (if possible).

closeQuietly() merely eats one exception but, as Goetz notes, "[n]early everything can throw an exception" in Java (http://www.koders.com/java/fid219DBE7E24ABBA5AA65548B0305BD6786EF5DF22.aspx?s=package+org.apache.commons.io+IOUtils.java#L17).

indranil banerjee

Posts: 38
Nickname: indranil
Registered: Nov, 2004

Re: Sources of Java Errors Posted: May 27, 2008 1:10 PM
Reply to this message Reply
Looks like there are many libraries that provide a closeQuietly method for cleanup.

http://www.google.com/codesearch?q=lang%3Ajava+closeQuietly&hl=en

This goes someway to reduce the error handling boilerplate code that you have to write in Java. But the onus is still on the developer to call closeQuietly for all closable resources everytime they are used.

I'm looking for an abstraction that looks after resource cleanup with a simple interface that doesnt get in the way of the business logic of the function at hand.

Roland has mentioned RAII, but I'd really like to see code (in the language of your choice) that does the same job as the snippet I posted earlier.

Morgan Conrad

Posts: 307
Nickname: miata71
Registered: Mar, 2006

Re: Sources of Java Errors Posted: May 27, 2008 5:05 PM
Reply to this message Reply
> closeQuietly() merely eats one exception but, as
> Goetz notes, "[n]early everything can throw an exception"
> in Java

It eats the declared (and possibly expected) IOException. As for eating any shockingly unexpected RuntimeExceptions, it's not clear if you want to do that - depends on the application.

For many, that's a crash, you definitely want to throw the exception and basically exit. Cleanup of resources is LESS important that getting a clean stack dump. YMMV.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Sources of Java Errors Posted: May 29, 2008 11:58 AM
Reply to this message Reply
> With RAII you don't have those problems because cleanup is
> defined once per class, not each time the resource is
> used. If Java had RAII you could spare 95% of all
> try/catch/finally blocks in the code. Lack of RAII is
> responsible for most of Java's proverbial verbosity.

I'm not going to say RAII isn't useful but there are other approaches to address the issue. I've written a library that addresses this issue in Java for databases.

A database query might look something like this:
Query query = Manager.getQuery("select bar from foo");
 
query.execute(new Handler() {
    public void handle(Row row)
    {
       // do things with row
    }
});


The resource cleanup is handled by the manager.

dark mx

Posts: 7
Nickname: darkmx0z
Registered: Mar, 2008

Re: Sources of Java Errors Posted: Jun 1, 2008 7:47 AM
Reply to this message Reply
example of RAII in C++


class File {
public:
File(const string& path) // constructor
: h_(open_file(path))
{
if (h_ == 0) {
throw "Could not open " + path;
}
}

~File( ) // destructor
{
close( );
}

void close( ) // for completeness
{
if (h_ != 0) {
close_file(h_);
}
}

private:
Handle h_;
};


using this class:


function foo(const string& path)
{
File f(path);
g( ); // may throw an exception

// no need to close f manually before the }
// no need to catch the exception to close f
}



Any File instance will be closed at the end of its scope or when an exception forces the stack to be cleaned. f will be deterministicly closed even in an exception was thrown.

Flat View: This topic has 29 replies on 2 pages [ « | 1  2 ]
Topic: Scala Tendencies and Concurrency Previous Topic   Next Topic Topic: Next-Generation Object-Oriented Databases

Sponsored Links



Google
  Web Artima.com   

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