try with resources not available on Android,
if you want to target wide range of devices,
so I want emulate something like it, with such semantic:
No exceptions - close, and throw exception if close failed
Has exception - close and ignore close exceptions
Is such code suppose to work as I want or I missed something? And may be possible to simplify it in some way?
final Closeable closebale = ...;
try {
//work with closeable
} catch (IOException e) {
try {
closeable.close();
} catch (IOException e2) {
//log exception
}
closeable = null;
throw e;
} finally {
if (closeable != null) {
//we not catch any exception
closeable.close();
}
}
The historical pattern in Java is:
Closeable foo = null;
try
{
foo = ...;
...
}
finally
{
if (foo != null)
{ foo.close(); }
}
You may put the call to .close() in a try-catch block if you wish to catch and either handle or suppress any exceptions that occur during the attempt to close the resource. I recommend against suppressing exceptions. At a minimum you should log them.
Related
I have the following code which is java 1.7 compatible, however, I need it to be compatible with java 1.6. currently I get the following error for this code: try-with-resources is not supported in -source 1.6
the code looks like this:
try (QueryExecution qexec = QueryExecutionFactory.create(query, input.getModel())) {
// Some other code
while (results.hasNext()) {
// do something
}
return something;
}
what do I need to change in order to make it work with java 1.6?
The real answer:
The real answer here is use Java 7 or 8. Java 6 is very old. Java 7 came out four years ago; Java 8, almost a year and a half.
Only keep reading if there's a very, very good reason you can't do that. :-)
TL;DR
That specific example can be simply:
QueryExecution qexec = QueryExecutionFactory.create(query, input.getModel());
Throwable thrown = null;
try {
// Some other code
while (results.hasNext()) {
// do something
}
return something;
}
catch (Throwable t) {
thrown = t; // Remember we're handling an exception
throw t;
}
finally {
try {
qexec.close();
}
catch (Throwable t) {
if (thrown == null) {
// Not handling an exception, we can rethrow
throw t;
}
else {
// Log it or something, you can't allow it to
// throw because there's *already* an exception
// being thrown and you'll hide it. This is why
// Java 7 added Throwable#addSuppressed.
}
}
}
But that's because it's a very simple case. If there were any other resources that needed closing (results, for instance?) or you were handling some exceptions in the code itself, it would be more complicated.
The more general form is;
SomeResource r1 = null;
Throwable thrown = null;
try {
r1 = new SomeResource();
SomeOtherResource r2 = null;
try {
r2 = new SomeOtherResource();
// use them
return something;
}
catch (Throwable t) {
thrown = t; // Remember we're handling an exception
throw t;
}
finally {
try {
r2.close();
}
catch (Throwable t) {
if (thrown == null) {
// Not handling an exception, we can rethrow
throw t;
}
else {
// Log it or something, you can't allow it to
// throw because there's *already* an exception
// being thrown and you'll hide it. This is why
// Java 7 added Throwable#addSuppressed.
}
}
}
}
catch (Throwable t) {
thrown = t; // Remember we're handling an exception
throw t;
}
finally {
try {
r1.close();
}
catch (Throwable t) {
if (thrown == null) {
// Not handling an exception, we can rethrow
throw t;
}
else {
// Log it or something
}
}
}
You'll probably want some utility library functions to help with this, it's a lot of boilerplate otherwise. I used to have things that did "silent" closes for the case where I knew an exception was already happening.
Details: This is covered by ยง14.20.3 of the JLS and its subsections:
A simple try-with-resources:
try ({VariableModifier} R Identifier = Expression ...)
Block
translates to:
{
final {VariableModifierNoFinal} R Identifier = Expression;
Throwable #primaryExc = null;
try ResourceSpecification_tail
Block
catch (Throwable #t) {
#primaryExc = #t;
throw #t;
} finally {
if (Identifier != null) {
if (#primaryExc != null) {
try {
Identifier.close();
} catch (Throwable #suppressedExc) {
#primaryExc.addSuppressed(#suppressedExc);
}
} else {
Identifier.close();
}
}
}
}
You'll have to remove the addSuppressed part as Throwable didn't have that in JDK6.
An extended try-with-resources:
try ResourceSpecification
Block
[Catches]
[Finally]
translates to:
try {
try ResourceSpecification
Block
}
[Catches]
[Finally]
...where that
try ResourceSpecification
Block
...is replaced by the big thing that the simple try-with-resources turns into, so the whole thing turns into:
try {
{
final {VariableModifierNoFinal} R Identifier = Expression;
Throwable #primaryExc = null;
try ResourceSpecification_tail
Block
catch (Throwable #t) {
#primaryExc = #t;
throw #t;
} finally {
if (Identifier != null) {
if (#primaryExc != null) {
try {
Identifier.close();
} catch (Throwable #suppressedExc) {
#primaryExc.addSuppressed(#suppressedExc);
}
} else {
Identifier.close();
}
}
}
}
}
[Catches]
[Finally]
...which is why we love the try-with-resources statement so much.
what do I need to change in order to make it work with java 1.6?
Try the following code:
QueryExecution qexec = null;
try {
qexec = QueryExecutionFactory.create(query, input.getModel()));
// Some other code
while (results.hasNext()) {
// do something
}
return something;
} finally {
if (qexec != null){
qexec.close();
}
}
The most imporant part: the streams have to be closed manually in the finally block.
Please note however that Oracle Java SE 6 and now even Oracle Java SE 7 reached EoL. So if you're using the implementation from Oracle and don't have according support contracts then it's strongly recommended to upgrade to Java SE 8
Assuming Java6, is this code safe from file descriptor leak:
{
InputStream in = fileObject.getReadStream();
// fileObject cleans it's internal state in case it throws exception
try {
// do whatever, possibly throwing exception
} finally {
try {
in.close();
} catch (Exception ex) {
// failure to close input stream is no problem
}
}
}
Edit: To make question seem less obvious, to state it other way, is above code equal to this longer code:
{
InputStream in = null;
try {
in = fileObject.getReadStream();
// fileObject cleans it's internal state in case it throws exception
// do whatever, possibly throwing exception
} finally {
if (in != null) {
try {
in.close();
} catch (Exception ex) {
// failure to close input stream is no problem
}
}
}
}
That is, does it matter whether a call to a method which returns opened stream or throws exception is immediately before try, or inside the try block?
Yes, fine. Does not even merit an answer. A variant (I less use) is:
InputStream in = null;
try {
in = fileObject.getReadStream();
// do whatever, possibly throwing exception
} finally {
if (in != null) {
try {
in.close();
} catch (Exception ex) {
// failure to close input stream is no problem if everything else was ok
}
}
}
I'm a student not very familiar with Java, but I wish I can help you a litltle.
I think that the piece of code can't keep you from the problem of file descriptor leak. Though you have let a try clouse wurround the in.close methord, but that won't help if
the in.close method throws some exceptions.
The general rule of exceptions is that you catch more specific ones before catching general ones. I have a case where closing a server throws SocketException: socket closed coming from my listener which is caught by IOException, but I don't want to show the user that message when they close the server. Everything else is probably an actual error so it should be shown to them, so I catch SocketException, check its message and if it is not socket closed then it should be rethrown to be caught and handled as an IOException. Java/NetBeans 7.0.1 do not seem to like that. Here is my code:
public void run() {
while (runner == Thread.currentThread()) {
System.out.println("waiting for connection...");
try {
Socket s = server.accept(); //throws SocketException/IOException
if (session == null) {
session = new ReceiveSession(s, parent);
} else {
s.close();
}
} catch (SocketException e) {
if (!e.getMessage().equals("socket closed")) {
throw e; //error line, "unreported exception SocketException"
}
} catch (IOException e) {
e.printStackTrace();
parent.showError("Someone tried to connect but the connection failed: " + e);
session = null;
}
}
}
When trying to clean and build, I get:
error: unreported exception SocketException; must be caught or declared to be thrown
throw e;
1 error
Since SocketException extends IOException, it should be caught by the more general IOException. Why do I get this error? (Running the project as is in NetBeans works perfectly btw, it doesn't show the user the exception when the server shuts down as I want.)
Your throw is outside the try block, so the thrown exception will not be handled by the catch below.
The second catch will not catch the rethrow since it wasn't thrown in the try block for which the second catch is responsible. You'll need to restructure the code.
For example, the most straight forward restructuring would be this:
public void run() {
while (runner == Thread.currentThread()) {
System.out.println("waiting for connection...");
try {
try {
Socket s = server.accept(); //throws SocketException/IOException
if (session == null) {
session = new ReceiveSession(s, parent);
} else {
s.close();
}
} catch (SocketException e) {
if (!e.getMessage().equals("socket closed")) {
throw e; //error line, "unreported exception SocketException"
}
}
} catch (IOException e) {
e.printStackTrace();
parent.showError("Someone tried to connect but the connection failed: " + e);
session = null;
}
}
}
The nested tries make me cry a little, but it would get the job done (and to be honest, off the top of my head, I can't think of a better way that doesn't go way too far).
Catch statements catch exceptions from their respective try block, not from other catch blocks in the list. You're throwing the exception from outside the try, so it does not get caught by subsequent catch blocks.
I have a try with several different catches after it. I have some "cleanup" code that only should be run if there was an exception thrown. I could add the same code to each exception, but that becomes a maintenance nightmare. Basically, I'd like something like the finally statement, but for it to only run if an exception was thrown.
Is this possible?
There is no direct support for this unfortunately. How about something like this
boolean successful = false;
try {
// do stuff
successful = true;
} catch (...) {
...
} finally {
if (!successful) {
// cleanup
}
}
The only thing I can think of is to set a variable in each catch and then check for that variable in finally.
Pseudocode:
Boolean caught = false;
try {
//risky code here
catch(err) {
caught = true;
// Do other stuff
}
catch(err) {
caught = true;
// Do other stuff
}
catch(err) {
caught = true;
// Do other stuff
}
finally {
if (caught) {
// Do clean up
}
}
I could add the same code to each exception, but that becomes a maintenance nightmare.
Or if you blot out the 'exception':
I could add the same code to each [place], but that becomes a maintenance nightmare.
This is what methods are made for.
private void cleanup() { /* clean up */ }
...
try {
// oh noes
} catch (MyException me) {
cleanup();
} catch (AnotherException ae) {
cleanup();
}
Maintenance hassle gone!
Why don't you just use simple try & catch?
try
{
foo();
}
catch(Exception1 e1)
{
dealWithError(1);
}
catch(Exception2 e2)
{
dealWithError(2);
}
catch(Exception3 e3)
{
dealWithError(3);
}
...
private void dealWithError(int i)
{
if(i == 1) // deal with Exception1
else if(i == 2) // deal with Exception2
else if(i == 3) // deal with Exception3
}
You could try wrapping two layers of exception handlers, and rethrow the exception after you have done the common handling:
try {
try {
// your code goes here
} catch (Throwable t) {
// do common exception handling for any exception
throw t;
}
} catch (NullPointerException nx) {
// handle NPE
} catch (Throwable t) {
// handle any other exception
}
Not sure I really like this solution though... feels like a bit of a hack. I'd probably rather see the Exception explicitly handled in each instance, even if this means repeating a call to some kind of shared cleanup function.
Usually, when dealing with Java IO code, here is what I wrote
FileOutputStream out = null;
try
{
out = new FileOutputStream("myfile.txt");
// More and more code goes here...
}
catch (Exception e)
{
}
finally
{
// I put the close code in finally block, to enture the opened
// file stream is always closed even there is exception happened.
if (out != null) {
// Another try catch block, troublesome.
try {
out.close();
} catch (IOException ex) {
}
}
}
As you can see, while I try to close the file stream, I need to deal with another try...catch block.
Look troublesome :(
Is there any way I can avoid? I don't feel comfortable in putting the close code in non-finally block, as exception caused by other codes will make no chance for "close" being called.
It is very important that you close streams in a finally. You can simplify this process with a utility method such as:
public static void closeStream(Closeable closeable) {
if(null != closeable) {
try {
closeable.close();
} catch(IOException ex) {
LOG.warning("Failed to properly close closeable.", ex);
}
}
}
I make it a point of at least logging a stream close failure. The usage then becomes:
FileOutputStream out = null;
try
{
out = new FileOutputStream("myfile.txt");
// More and more code goes here...
}
catch (Exception e)
{
}
finally
{
closeStream(out);
}
In Java 7 I believe that streams will be closed automatically and the need for such blocks should be mostly redundant.
Automatic Resource Management is coming in Java 7 which will automatically provide handling of this. Until then, objects such as OutputStream, InputStream and others implement the Closeable interface since Java 5. I suggest you provide a utility method to safe close these. These methods generally eat exceptions so make sure that you only use them when you want to ignore exceptions (e.g. in finally method). For example:
public class IOUtils {
public static void safeClose(Closeable c) {
try {
if (c != null)
c.close();
} catch (IOException e) {
}
}
}
Note that the close() method can be called multiple times, if it is already closed subsequent calls will have no effect, so also provide a call to close during the normal operation of the try block where an exception will not be ignored. From the Closeable.close documentation:
If the stream is already closed then invoking this method has no effect
So close the output stream in the regular flow of the code and the safeClose method will only perform close if something failed in the try block:
FileOutputStream out = null;
try {
out = new FileOutputStream("myfile.txt");
//...
out.close();
out = null;
} finally {
IOUtils.safeClose(out);
}
Discussion at
Try-catch-finally and then again a try catch
and
Is there a preference for nested try/catch blocks?
basically, the question is whether a close() exception is worth catching.
Project Lombok provides a #Cleanup annotation that removes the need for try catch blocks all together. Here's an example.
I tend to use utility functions for this:
public static void safeClose(OutputStream out) {
try {
out.close();
} catch (Exception e) {
// do nothing
}
}
which changes the code to the slightly more palatable:
FileOutputStream out = null;
try {
out = new FileOutputStream("myfile.txt");
// do stuff
} catch (Exception e) {
// do something
} finally {
safeClose(out);
}
You can't really do much better in Java at least until Java 7 when (hopefully) ARM ("Automatic Resource Management") blocks will help somewhat.
Write a method that looks something like below; call from your finally block...
static void wrappedClose(OutputStream os) {
if (os != null) {
try {
os.close();
}
catch (IOException ex) {
// perhaps log something here?
}
}
Separate your try/catch and try/finally blocks.
try
{
FileOutputStream out = new FileOutputStream("myfile.txt");
try
{
// More and more code goes here...
}
finally
{
out.close();
}
}
catch (Exception e)
{
//handle all exceptions
}
The outer catch will also catch anything thrown by the close.