Reducing try-catch blocks in Java code to improve performance - java

I have been given the task of reducing try-catch blocks in my Java code for increasing performance. But each try block is checking for a entirely different kind of exception and that too custom exceptions. How to reduce the try-catch blocks.
The sample of a part of my code is as follows:-
// Get a test engine and use that to initialize and save the test
// taker
TestEngine testEngine = null;
try {
testEngine = objFactory.getTestEngine(login.getTestengine());
} catch (NoTestEngineException e) {
// Add an error message, then throw the exception to struts to
// handle
request.setAttribute("errmsg", "Cannot create test engine: " + login.getTestengine());
request.setAttribute("errcause", "exception.notestengine.cause");
throw e;
}
//added for null check of variable testEngine
if(testEngine==null)
{
request.setAttribute("errmsg", "Could not obtain a testengine");
}
// Do we need to save the session id?
String saveSessionId = objFactory.getConfigValue("testengine." + login.getTestengine() + ".recordjessionid", "false");
String sessionId = null;
if (saveSessionId.trim().equals("true")) {
sessionId = request.getSession().getId();
}
Testtaker testTaker = null;
try {
testTaker = testEngine.buildTestTaker(login, null, sessionId, null, null);
} catch (Exception e) {
request.getSession().removeAttribute(ConstantLibrary.SESSION_LOGIN);
CaslsUtils.outputLoggingData(log_, request);
// Add an error message, then throw the exception to struts to
// handle
request.setAttribute("errmsg", "Cannot build a test taker.");
request.setAttribute("errcause", "exception.testtakerbuildfailed.cause");
//throw new NoTestTakerException("Failed to build testtaker.");
throw e;
}

If your exception type is different for each block in that case you can join your try block to one and add multiple catch block to a with single try block
try {
TestEngine testEngine = objFactory.getTestEngine(login.getTestengine());
//added for null check of variable testEngine
if(testEngine==null) {
request.setAttribute("errmsg", "Could not obtain a testengine");
}
// Do we need to save the session id?
String saveSessionId = objFactory.getConfigValue("testengine." + login.getTestengine() + ".recordjessionid", "false");
String sessionId = null;
if (saveSessionId.trim().equals("true")) {
sessionId = request.getSession().getId();
}
Testtaker testTaker = testEngine.buildTestTaker(login, null, sessionId, null, null);
} catch (NoTestEngineException e) {
// Add an error message, then throw the exception to struts to
// handle
request.setAttribute("errmsg", "Cannot create test engine: " + login.getTestengine());
request.setAttribute("errcause", "exception.notestengine.cause");
throw e;
} catch (Exception e) {
request.getSession().removeAttribute(ConstantLibrary.SESSION_LOGIN);
CaslsUtils.outputLoggingData(log_, request);
// Add an error message, then throw the exception to struts to
// handle
request.setAttribute("errmsg", "Cannot build a test taker.");
request.setAttribute("errcause", "exception.testtakerbuildfailed.cause");
//throw new NoTestTakerException("Failed to build testtaker.");
throw e;
}

You can change two try-catch blocks into one:
TestEngine testEngine = null;
Testtaker testTaker = null;
try {
testEngine = objFactory.getTestEngine(login.getTestengine());
String saveSessionId =
objFactory.getConfigValue("testengine." + login.getTestengine() + ".recordjessionid", "false");
String sessionId = saveSessionId.trim().equals("true") ?
request.getSession().getId() : null;
testTaker = testEngine.buildTestTaker(login, null, sessionId, null, null);
}
catch (NoTestEngineException e) {
// Add an error message, then throw the exception to struts to handle
request.setAttribute("errmsg", "Cannot create test engine: " + login.getTestengine());
request.setAttribute("errcause", "exception.notestengine.cause");
throw e;
}
catch (Exception e) {
request.getSession().removeAttribute(ConstantLibrary.SESSION_LOGIN);
CaslsUtils.outputLoggingData(log_, request);
// Add an error message, then throw the exception to struts to handle
request.setAttribute("errmsg", "Cannot build a test taker.");
request.setAttribute("errcause", "exception.testtakerbuildfailed.cause");
throw e;
}

I would write it like this
public void someMethod(... args) throws Exception {
// taker
TestEngine testEngine = objFactory.getTestEngine(login.getTestengine());
// Do we need to save the session id?
String saveSessionId = objFactory.getConfigValue("testengine." + login.getTestengine() + ".recordjessionid", "false");
String sessionId = null;
if (saveSessionId.trim().equals("true")) {
sessionId = request.getSession().getId();
}
Testtaker testTaker = testEngine.buildTestTaker(login, null, sessionId, null,
}
And I would have the caller handle any exceptions.

Unlike C++, try-catch-finally blocks (exceptions) are essential parts of Java; they should be used and used properly. I also don't think they have significant performance effects; they will be thrown anyway even if you don't catch them (will be caught by the main thread finally). But for aesthetical reasons, you may reorganize them or use a single one for the whole method as in:
method() {
try {
} catch (Ex1 e1) {
} catch (Ex2 e2) {
} finally {
}
}
you can also consider processing them, not throwing again and processing in every method in the call stack (this may have -a bit of?- performance impact..)..

As the comments have noted, the number of try/catch blocks aren't the problem - it's the fact you're hitting them so often that is.
Assuming that you've analysed the performance and it is actually this method that is giving you issues, you should take the obvious steps to avoid exceptions being thrown (and the stack unwound as a result).
For example, you're not returning from the method if testEngine is null after the getTestEngine() call, but you're going to immediately get a NPE after testEngine.buildTestTaker(), hitting one of your catch blocks. Instead you should return from the method (with an appropriate error code) if testEngine is null, avoiding the stack unwind penalty.

Related

Android crash report shows exception that is caught

I have an Android app written in Java, and recently noticed many crash reports occurring in an AsyncTask. The stack trace makes no sense, as it is inside a try/catch so there is no way for the exception to be thrown. How can a caught exception cause an app crash?
13: public class HttpGoogleSignInAction...
#Override
protected String doInBackground(Void... voids) {
try {
// Check if user exists
UserConfig user = null;
31: user = MainActivity.connection.fetch(this.config);
if (user == null) {
} else {
// User exists, try to sign in user
this.config = MainActivity.connection.connect(this.config);
}
} catch (Exception userDoesNotExist) {
try {
// User does not exist, try to create user
this.config = MainActivity.connection.create(this.config);
} catch (Exception exception) {
this.exception = exception;
}
}
return "";
}
public String POST(String url, String xml) {
if (this.debug) {
System.out.println("POST: " + url);
System.out.println("XML: " + xml);
}
String result = "";
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
StringEntity content = new StringEntity(xml, "utf-8");
content.setContentType("application/xml");
httpPost.setEntity(content);
HttpResponse response = httpClient.execute(httpPost, localContext);
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity, HTTP.UTF_8);
}
if ((response.getStatusLine().getStatusCode() != 200) && (response.getStatusLine().getStatusCode() != 204)) {
this.exception = new SDKException(""
+ response.getStatusLine().getStatusCode()
+ " : " + result);
2205: throw this.exception;
}
} catch (Exception exception) {
if (this.debug) {
exception.printStackTrace();
}
this.exception = new SDKException(exception);
2213: throw this.exception;
}
return result;
}
The stack trace shows the crash occurring in the line,
user = MainActivity.connection.fetch(this.config);
It is a normal RuntimeException subclass exception being thrown, which should be caught. If I try to force an exception to test it the try/catch works fine and no crash, but in 1% of users using the app I am seeing crashes, others it works fine.
Makes no sense.
This is the stack trace from Google Play, SDKException is a subclass of RuntimeException, the line of code it occurs in is inside try/catch
org.botlibre.sdk.SDKException:
at org.botlibre.sdk.SDKConnection.POST (SDKConnection.java:2213)
at org.botlibre.sdk.SDKConnection.fetch (SDKConnection.java:259)
at ...HttpGoogleSignInAction.doInBackground (HttpGoogleSignInAction.java:31)
at ...HttpGoogleSignInAction.doInBackground (HttpGoogleSignInAction.java:13)
at android.os.AsyncTask$3.call (AsyncTask.java:394)
at java.util.concurrent.FutureTask.run (FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run (AsyncTask.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
at java.lang.Thread.run (Thread.java:923)
Caused by: org.botlibre.sdk.SDKException:
at org.botlibre.sdk.SDKConnection.POST (SDKConnection.java:2205)
org.botlibre.sdk.SDKException:
at org.botlibre.sdk.SDKConnection.POST (SDKConnection.java:2213)
at org.botlibre.sdk.SDKConnection.fetch (SDKConnection.java:259)
Shows that you're throwing the exception captured here in doInBackground():
try {
// User does not exist, try to create user
this.config = MainActivity.connection.create(this.config);
} catch (Exception exception) {
**this.exception = exception;**
}
}
Even though this execption is within a catch block, since it's persisted and then thrown later it is now outside of a try-catch block and can crash the app. That is
try {
...
} catch (Exception exception) {
if (this.debug) {
exception.printStackTrace();
}
this.exception = new SDKException(exception);
// This line will throw an execption that will have the message from the original exception.
2213: throw this.exception;
}
The source for SDKException's single exception constructor shows it reuses the message from the exception parameter.
You are very clearly re-throwing the caught exception on line 2213. If you throw an exception from a catch block, it escapes the try/catch because you are throwing it from a scope of code that is not surrounded by try { }.
As for why fetch() might be throwing, we would have to see the code to be able to guess.
Even though you have your code wrapped in try catch, there is a possibility of a crash if different threads are involved. try catch does not catch exceptions from child threads, so if any of your methods(like .fetch or .connect) used in doInBackground are internally using/creating different threads and an exception is thrown within that thread it might cause the app to crash. Looking at the logs, it is possible the .fetch method is asynchronous and performing operations in a different thread.

Should I re-throw an exception after logging it?

I find myself coding methods that throw a specified error, but still surrounding the relevant code sections in a try catch, where I use the catch to log a localised error message and re-throw the principal one.
Here is a short example:
public void doWork(String url) throws IOException {
Object target;
try {
target = new target(url); //instantiating this object could potentially not work if the URL is malformed
} catch (MalformedURLException e) {
localErrorMessage(debug, "URL error here"); //log a local message
throw e;
} catch (IOException e) { //in some cases it can throw an IO exception if using a localised file type object.
localErrorMessage(debug, "IO error here"); //log a local message throw e;
}
}
I use this as I can turn off my localised logging (using log4j2), or use it during testing, as a debugging method.
Is this a reasonable practice, or is there a better way to do it?

How to avoid throw clause in finally block

I am using SonarQube for code quality. I got one issue related to exception handling, which says remove throw clause from finally block.
} catch(Exception e) {
throw new MyException("request failed : ", e);
} finally {
try {
httpClient.close();
} catch (IOException e) {
throw new MyException("failed to close server conn: ", e);
}
}
Based on my understanding above code looks good. If I remove throw clause and suppress exception in finally then caller of this method will not be able to know server's status. I am not sure how we can achieve same functionality without having throw clause.
Your best shot is to use the Automatic Resource Management feature of Java, available since Java 7. If that is for some reason not available to you, then the next best thing is to replicate what that syntactic sugar expands into:
public static void runWithoutMasking() throws MyException {
AutoClose autoClose = new AutoClose();
MyException myException = null;
try {
autoClose.work();
} catch (MyException e) {
myException = e;
throw e;
} finally {
if (myException != null) {
try {
autoClose.close();
} catch (Throwable t) {
myException.addSuppressed(t);
}
} else {
autoClose.close();
}
}
}
Things to note:
your code swallows the original exception from the try block in case closing the resource fails. The original exception is surely more important for diagnostic;
in the ARM idiom above, closing the resource is done differently depending on whether there already was an exception in the try-block. If try completed normally, then the resource is closed outside any try-catch block, naturally propagating any exception.
Generally, methods in the finally block are 'cleanup' codes (Closing the Connection, etc) which the user does not necessarily need to know.
What I do for these exceptions is to absorb the exception, but log the details.
finally{
try{
connection.close();
}catch(SQLException e){
// do nothing and just log the error
LOG.error("Something happened while closing connection. Cause: " + e.getMessage());
}
}
You're getting a warning because this code could potentially throw an exception while dealing with a thrown exception. You can use the try with resource syntax to close the resource automatically. Read more here.
In the case that the "request failed : " exception is thrown and you fail to close the httpclient, the second exception is the one that would bubble up.
I am not sure how we can achieve same functionality without having
throw clause.
You could nest the two try blocks differently to achieve the same result:
HttpClient httpClient = null; // initialize
try {
try {
// do something with httpClient
} catch(Exception e) {
throw new MyException("request failed : ", e);
} finally {
httpClient.close();
}
} catch (IOException e) {
throw new MyException("failed to close server conn: ", e);
}

rethrow java exception with new message, preserving the exception type if it is in the method declaration list

I am trying to create a helper method that will eliminate the need of having code like this:
void foo() throws ExceptionA, ExceptionB, DefaultException {
try {
doSomething(); // that throws ExceptionA, ExceptionB or others
} catch (Exception e) {
if (e instanceof ExceptionA)
throw new ExceptionA("extra message", e);
if (e instanceof ExceptionB)
throw new ExceptionB("extra message", e);
throw new DefaultException("extra message", e);
}
}
The problem is that I need to maintain the throws list in the function declaration and in the body of the function at the same time. I am looking how to avoid that and to make changing the throws list sufficient and my code to looks like:
void foo() throws ExceptionA, ExceptionB, DefaultException {
try {
doSomething(); // that throws ExceptionA, ExceptionB or others
} catch (Exception e) {
rethrow(DefaultException.class, "extra message", e);
}
}
Where rethrow method will be smart enough to recognize the throws list from the method declaration.
This way when I change the list of type that my method propagates in the throws list I to not need to change the body.
The following is a function that could solve the problem. The problem is because it does not know what type of exception it will throw its throws declaration has to say Exception, but if it does this, the method that is going to use it will need to specify it as well, and the whole idea of using the throws list goes to hell.
Any suggestions how this could be solved?
#SuppressWarnings("unchecked")
public static void rethrow(Class<?> defaultException, String message, Exception e) throws Exception
{
final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
final StackTraceElement element = ste[ste.length - 1 - 1];
Method method = null;
try {
method = getMethod(element);
} catch (ClassNotFoundException ignore) {
// ignore the Class not found exception - just make sure the method is null
method = null;
}
boolean preserveType = true;
if (method != null) {
// if we obtained the method successfully - preserve the type
// only if it is in the list of the thrown exceptions
preserveType = false;
final Class<?> exceptions[] = method.getExceptionTypes();
for (Class<?> cls : exceptions) {
if (cls.isInstance(e)) {
preserveType = true;
break;
}
}
}
if (preserveType)
{
// it is throws exception - preserve the type
Constructor<Exception> constructor;
Exception newEx = null;
try {
constructor = ((Constructor<Exception>) e.getClass().getConstructor());
newEx = constructor.newInstance(message, e);
} catch (Exception ignore) {
// ignore this exception we prefer to throw the original
newEx = null;
}
if (newEx != null)
throw newEx;
}
// if we get here this means we do not want, or we cannot preserve the type
// just rethrow it with the default type
Constructor<Exception> constructor;
Exception newEx = null;
if (defaultException != null) {
try {
constructor = (Constructor<Exception>) defaultException.getConstructor();
newEx = constructor.newInstance(message, e);
} catch (Exception ignore) {
// ignore this exception we prefer to throw the original
newEx = null;
}
if (newEx != null)
throw newEx;
}
// if we get here we were unable to construct the default exception
// there lets log the message that we are going to lose and rethrow
// the original exception
log.warn("this message was not propagated as part of the exception: \"" + message + "\"");
throw e;
}
Update 1:
I can use RuntimeException to avoid the need of throws declaration, but in this case I am losing the type of the exception which is one of the most important points.
Ideas how I can resolve this?
I'm guessing that code where you're doing real work (ie. the part where you're not tinkering with exceptions) looks like this.
public void doSomeWork( ... ) throws ExceptionA, ExceptionB, DefaultException
{
try
{
// some code that could throw ExceptionA
...
// some code that could throw OtherExceptionA
...
// some code that could throw ExceptionB
...
// some code that could throw OtherExceptionB
}
catch (Exception e)
{
if( e instanceof ExceptionA )
{
throw new ExceptionA("extra message", e);
}
if( e instanceof ExceptionB )
{
throw new ExceptionB("extra message", e);
}
throw new DefaultException("extra message", e);
}
}
There are two better approaches
First Approach
public void doSomeWork( ... ) throws ExceptionA, ExceptionB, DefaultException
{
// some code that could throw ExceptionA
...
try
{
// some code that could throw OtherExceptionA
...
}
catch (Exception e)
{
throw new DefaultException("extra message", e);
}
// some code that could throw ExceptionB
...
try
{
// some code that could throw OtherExceptionB
}
catch (Exception e)
{
throw new DefaultException("extra message", e);
}
}
Second Approach
public void doSomeWork( ... ) throws ExceptionA, ExceptionB, DefaultException
{
try
{
// some code that could throw ExceptionA
...
// some code that could throw OtherExceptionA
...
// some code that could throw ExceptionB
...
// some code that could throw OtherExceptionB
}
catch (OtherExceptionA | OtherExceptionB e)
{
throw new DefaultException("extra message", e);
}
}
The first approach is good if you want to continue execution at all costs and catch and wrap RuntimeExceptions if you run into them. Generally you don't want to do this, and it's better to let them propagate up, as you probably can't handle them.
The second approach is generally the best. Here you're explicitly pointing out which exceptions you can handle, and dealing with them by wrapping them. Unexpected RuntimeExceptions propagate up, as they should unless you have some way of dealing with them.
Just a general comment: playing with StackTraceElements isn't considered to be a great idea. You may end up getting an empty array from Thread.currentThread().getStackTrace() (although you most likely will not if using a modern Oracle JVM), and the depth of the calling method isn't always length-2, it may be length-1 particularly in older versions of the Oracle JVM.
You can read more about this problem in this question.
To elaborate on what )some) people are telling you, this is MyFunctionFailedException, ofcourse it should be named something more sensible:
public class MyFunctionFailedException extends Exception {
public MyFunctionFailedException(String message, Throwable cause) {
super(message, cause);
}
}
Then your catch block becomes something like this.
try {
...
} catch (Exception e) {
throw new MyFunctionFailedException("extra message", e);
}
If you really want to rethrow a lower level exception, you should use multiple catch blocks. Be aware tho' that not all types of Exceptions necessarily has a constructor that let's you add a cause. And you really should think about why it makes sense for your method to let for instance an uncaught SQLException bubble up the call stack.

throws Exception in finally blocks

Is there an elegant way to handle exceptions that are thrown in finally block?
For example:
try {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
finally {
try{
resource.close();
}
catch( Exception ex ) {
// Could not close the resource?
}
}
How do you avoid the try/catch in the finally block?
I usually do it like this:
try {
// Use the resource.
} catch( Exception ex ) {
// Problem with the resource.
} finally {
// Put away the resource.
closeQuietly( resource );
}
Elsewhere:
protected void closeQuietly( Resource resource ) {
try {
if (resource != null) {
resource.close();
}
} catch( Exception ex ) {
log( "Exception during Resource.close()", ex );
}
}
I typically use one of the closeQuietly methods in org.apache.commons.io.IOUtils:
public static void closeQuietly(OutputStream output) {
try {
if (output != null) {
output.close();
}
} catch (IOException ioe) {
// ignore
}
}
If you're using Java 7, and resource implements AutoClosable, you can do this (using InputStream as an example):
try (InputStream resource = getInputStream()) {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
Arguably a bit over the top, but maybe useful if you're letting exceptions bubble up and you can't log anything from within your method (e.g. because it's a library and you'd rather let the calling code handle exceptions and logging):
Resource resource = null;
boolean isSuccess = false;
try {
resource = Resource.create();
resource.use();
// Following line will only run if nothing above threw an exception.
isSuccess = true;
} finally {
if (resource != null) {
if (isSuccess) {
// let close throw the exception so it isn't swallowed.
resource.close();
} else {
try {
resource.close();
} catch (ResourceException ignore) {
// Just swallow this one because you don't want it
// to replace the one that came first (thrown above).
}
}
}
}
UPDATE: I looked into this a bit more and found a great blog post from someone who has clearly thought about this more than me: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html He goes one step further and combines the two exceptions into one, which I could see being useful in some cases.
As of Java 7 you no longer need to explicitly close resources in a finally block instead you can use try-with-resources syntax. The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
Assume the following code:
try( Connection con = null;
Statement stmt = con.createStatement();
Result rs= stmt.executeQuery(QUERY);)
{
count = rs.getInt(1);
}
If any exception happens the close method will be called on each of these three resources in opposite order in which they were created. It means the close method would be called first for ResultSetm then the Statement and at the end for the Connection object.
It's also important to know that any exceptions that occur when the close methods is automatically called are suppressed. These suppressed exceptions can be retrieved by getsuppressed() method defined in the Throwable class.
Source: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Ignoring exceptions which occur in a 'finally' block is generally a bad idea unless one knows what those exceptions will be and what conditions they will represent. In the normal try/finally usage pattern, the try block places things into a state the outside code won't be expecting, and the finally block restores those things' state to what the outside code expects. Outside code which catches an exception will generally expect that, despite the exception, everything has been restored to a normal state. For example, suppose some code starts a transaction and then tries to add two records; the "finally" block performs a "rollback if not committed" operation. A caller might be prepared for an exception to occur during the execution of the second "add" operation, and may expect that if it catches such an exception, the database will be in the state it was before either operation was attempted. If, however, a second exception occurs during the rollback, bad things could happen if the caller makes any assumptions about the database state. The rollback failure represents a major crisis--one which should not be caught by code expecting a mere "Failed to add record" exception.
My personal inclination would be to have a finally method catch exceptions that occur and wrap them in a "CleanupFailedException", recognizing that such failure represents a major problem and such an exception should not be caught lightly.
One solution, if the two Exceptions are two different classes
try {
...
}
catch(package1.Exception err)
{
...
}
catch(package2.Exception err)
{
...
}
finally
{
}
But sometimes you cannot avoid this second try-catch. e.g. for closing a stream
InputStream in=null;
try
{
in= new FileInputStream("File.txt");
(..)// do something that might throw an exception during the analysis of the file, e.g. a SQL error
}
catch(SQLException err)
{
//handle exception
}
finally
{
//at the end, we close the file
if(in!=null) try { in.close();} catch(IOException err) { /* ignore */ }
}
Why do you want to avoid the additional block? Since the finally block contains "normal" operations which may throw an exception AND you want the finally block to run completely you HAVE to catch exceptions.
If you don't expect the finally block to throw an exception and you don't know how to handle the exception anyway (you would just dump stack trace) let the exception bubble up the call stack (remove the try-catch from the finally block).
If you want to reduce typing you could implement a "global" outer try-catch block, which will catch all exceptions thrown in finally blocks:
try {
try {
...
} catch (Exception ex) {
...
} finally {
...
}
try {
...
} catch (Exception ex) {
...
} finally {
...
}
try {
...
} catch (Exception ex) {
...
} finally {
...
}
} catch (Exception ex) {
...
}
After lots of consideration, I find the following code best:
MyResource resource = null;
try {
resource = new MyResource();
resource.doSomethingFancy();
resource.close();
resource = null;
} finally {
closeQuietly(resource)
}
void closeQuietly(MyResource a) {
if (a!=null)
try {
a.close();
} catch (Exception e) {
//ignore
}
}
That code guarantees following:
The resource is freed when the code finished
Exceptions thrown when closing the resource are not consumed without processing them.
The code does not try to close the resource twice, no unnecessary exception will be created.
If you can you should test to avoid the error condition to begin with.
try{...}
catch(NullArgumentException nae){...}
finally
{
//or if resource had some useful function that tells you its open use that
if (resource != null)
{
resource.Close();
resource = null;//just to be explicit about it was closed
}
}
Also you should probably only be catching exceptions that you can recover from, if you can't recover then let it propagate to the top level of your program. If you can't test for an error condition that you will have to surround your code with a try catch block like you already have done (although I would recommend still catching specific, expected errors).
You could refactor this into another method ...
public void RealDoSuff()
{
try
{ DoStuff(); }
catch
{ // resource.close failed or something really weird is going on
// like an OutOfMemoryException
}
}
private void DoStuff()
{
try
{}
catch
{
}
finally
{
if (resource != null)
{
resource.close();
}
}
}
I usually do this:
MyResource r = null;
try {
// use resource
} finally {
if( r != null ) try {
r.close();
} catch( ThatSpecificExceptionOnClose teoc ){}
}
Rationale: If I'm done with the resource and the only problem I have is closing it, there is not much I can do about it. It doesn't make sense either to kill the whole thread if I'm done with the resource anyway.
This is one of the cases when at least for me, it is safe to ignore that checked exception.
To this day I haven't had any problem using this idiom.
try {
final Resource resource = acquire();
try {
use(resource);
} finally {
resource.release();
}
} catch (ResourceException exx) {
... sensible code ...
}
Job done. No null tests. Single catch, include acquire and release exceptions. Of course you can use the Execute Around idiom and only have to write it once for each resource type.
Changing Resource from best answer to Closeable
Streams implements Closeable Thus you can reuse the method for all streams
protected void closeQuietly(Closeable resource) {
if (resource == null)
return;
try {
resource.close();
} catch (IOException e) {
//log the exception
}
}
I encountered a situation similar where I couldn't use try with resources but I also wanted to handle the exception coming from the close, not just log and ignore it like closeQuietly mechanism do. in my case I'm not actually dealing with an output stream, so the failure on close is of more interest than a simple stream.
IOException ioException = null;
try {
outputStream.write("Something");
outputStream.flush();
} catch (IOException e) {
throw new ExportException("Unable to write to response stream", e);
}
finally {
try {
outputStream.close();
} catch (IOException e) {
ioException = e;
}
}
if (ioException != null) {
throw new ExportException("Unable to close outputstream", ioException);
}

Categories