Java resource management: understanding Findbugs results - java

Findbugs bugs me about a method which opens two Closeable instances, but I can't understand why.
Source
public static void sourceXmlToBeautifiedXml(File input, File output)
throws TransformerException, IOException, JAXBException {
FileReader fileReader = new FileReader(input);
FileWriter fileWriter = new FileWriter(output);
try {
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
} finally {
try {
fileReader.close();
} finally {
fileWriter.close();
}
}
}
Findbugs analysis
Findbugs tells me
Method [...] may fail to clean up java.io.Reader [...]
and points to the line with FileReader fileReader = ...
Question
Who is wrong: me or Findbugs?

FindBugs is correct: If the FileWriter's constructor throws an exception, the file reader will not be closed. To verify this, try passing an invalid filename for output.
I'd do it as follows:
FileReader fileReader = new FileReader(input);
try {
FileWriter fileWriter = new FileWriter(output);
try {
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
} finally {
fileWriter.close();
}
} finally {
fileReader.close();
}
Note that the handling of exception thrown when closing could be improved, since leaving a finally-block by throwing an exception will cause the try-statement to terminate by throwing that exception, swallowing any exception thrown in the try-block, which generally would be more useful for debugging. See duffymo's answer for a simple way on how to avoid this.
Edit: Since Java 7, we can use the try-with-resources statement, which permits correct and concicse handling of these corner cases:
try (
FileReader fileReader = new FileReader(input);
FileWriter fileWriter = new FileWriter(output)
) {
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
}

This may be complicated even for findbugs.
try {
fileReader.close();
} finally {
fileWriter.close();
}
Seems to me you are right.
EDIT : Wow, I thought I will get voted down for saying findbugs can be wrong!
EDIT : Looks like FindBugs is right after all. Good catch meriton.

i'd say it's you.
i'd close both resources in a separate try/catch block. i'd create static methods to help me:
public static void sourceXmlToBeautifiedXml(File input, File output)
throws TransformerException, IOException, JAXBException {
FileReader fileReader = new FileReader(input);
FileWriter fileWriter = new FileWriter(output);
try {
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
} finally {
close(fileReader);
close(fileWriter);
}
}
// same for reader & writer
public static void close(InputStream s)
{
try
{
if (s != null)
{
s.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}

I think findbugs is right.
} finally {
try {
fileReader.close();
} finally {
fileWriter.close();
}
}
In this block you try to close your FileReader. This however can throw an exception and in the nested finally you close the fileWriter. Have you tried closing both readers in the same finally block? What does findbugs say then?
} finally {
try {
fileReader.close();
fileWriter.close();
} finally {
//dunno maybe log that something went wrong.
}
}

Related

Is closing resources in try block accepted?

A beginners book on Java has the following code in it. This book also explains about exceptions very well, and since I understood how exception works, I got a question about the following code.
For some reason if FileWriter class throws an exception, writer.close() wouldn't be executed. Therefore I think the best place to close the writer object is in a finally block. Even prior to this I have seen many code written like this, where the resource will be closed in the try block itself. I think there is no point in doing so. Only when there is no exception the resource will be closed.
Am I wrong? What is the best way to close resources in java. Should we never write code like the following?
public static void main(String[] args) {
try{
FileWriter writer = new FileWriter("file.txt");
writer.write("i am writing");
writer.close();
}catch(IOException e){
ex.printStackTrace();
}
}
I agree with #cyber-rookie, it is probably best to close resources in a finally block.
Java 7 introduced "try-with-resources" in order to cut down on programming mistakes...
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
You can now write...
try (FileWriter writer = new FileWriter("file.txt")) {
writer.write("i am writing");
} catch (IOException e) {
e.printStackTrace();
}
The compiler will add the extra code to close the writer at the end of the block for you
If your are using Java 7, the best approach is to use try with resource. See https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
try (FileWriter writer = new FileWriter("file.txt")) {
writer.write("i am writing");
}
you are right, resource should be closed in finally block.
as of java 7 you can use try-with-resource also as :
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly if these resources implements AutoCloseable interface.
In my experience we would utilise the finally clause of a try-catch:
public static void main(String[] args) {
FileWriter writer = null;
try {
writer = new FileWriter("file.txt");
writer.write("i am writing");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
PS: Place this in separate method and throw the exception, let the class using this handle exceptions.
Answer to a comment to add multiple resources in a try with resource block:
try(FileWriter writer = new FileWriter("file.txt"); BufferedReader reader = new BufferedReader(new FileReader("file.txt"))){
// you can put many AUTOCLOSEABLE objects in try with resource. Just seperate them with ";"
} catch (IOException e) {
e.printStackTrace();
}
At work (Java 6), we close the resources in the TRY block then also do a defensive close in the FINALLY block.
BufferedReader bufferedReader;
try {
//initialize and do something with the bufferedReader
bufferedReader.close();
} catch (FileNotFoundException ex) {
// notify the user
} catch (IOException ex) {
// notify the user
} finally {
if (bufferedReader != null) {
try {
//defensive close
bufferedReader.close();
} catch (IOException ex) {
// this will be thrown if bufferedReader is already closed (in Try block, so can be leave to blank
}
}
}

calling a function: unreported IOException must be declared to be thrown

I have this code but there is an error to this,
I am not good with java so I posted my problem in here... this is my code
public static void SaveFile() throws IOException{
System.out.println("Saving File!");
FileWriter toTextFile = new FileWriter("output.txt");
for(x=0;x<new_num_book;x++){
toTextFile.write(name[x]);
}
toTextFile.close();
}
blah blah
else if(option == 5){
SaveFile();
}
the problem is that netbeans declares an error in accessing the SaveFile function. Please help! Thanks
saveFile throws an IOException, you need to handle it or pass it on to the caller.
Take a look at The try Block for more details
Without more context it's hard to say what you should do. You could handle the exception within the current method...
else if(option == 5){
try {
SaveFile();
} catch (IOException exp) {
// Handle the exception, tell the user, roll back, what ever
// At the very least use exp.printStackTrace()
}
}
or declare the current method as throwing an IOException like the SaveFile method does
Your SaveFile method is also, potentially, leaving the file open...
If the file writing process fails for some reason, toTextFile.close may never be called, instead, you should take advantage of the try-finally block, for example
public static void SaveFile() throws IOException{
System.out.println("Saving File!");
FileWriter toTextFile = null;
try {
toTextFile = new FileWriter("output.txt");
for(x=0;x<new_num_book;x++){
toTextFile.write(name[x]);
}
} finally {
try {
toTextFile.close();
} catch (Exception exp) {
}
}
}
or if you're using Java 7+, you can make use of the try-with-resources functionality, for example...
public static void SaveFile() throws IOException{
System.out.println("Saving File!");
try (FileWriter toTextFile = new FileWriter("output.txt")) {
for(x=0;x<new_num_book;x++){
toTextFile.write(name[x]);
}
}
}
You may also want to have a read of Lesson: Exceptions and Code Conventions for the Java TM Programming Language, which will make it easier for people to read your code and for you to read others

Preferred way to clean-up resources in Java 1.6

I regularly see this style of resource clean-up:
InputStream in = null;
try {
in = new FileInputStream(file);
// ...
} finally {
if (in != null) {
in.close();
}
}
I have always used the following style:
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
But am I missing something? Is there an advantage to the former that I'm not seeing?
I suspect its to avoid having two nested try/catch blocks instead of one.
InputStream in = null;
try {
in = new FileInputStream(file);
// ...
} catch(IOException ioe) {
// handle exception.
} finally {
IOUtils.closeQuietly(in);
}
The second case is incomplete.
try {
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
} catch(IOException e) {
// handle exception
}
If you have multiple files, this could get really messy.
Suppose that in the first example you have some other code before defining in that gets you out of the try block. If you get to the finally without in been defined you will get a NullPointerException when trying to close it. So you will have to make the check to avoid errors like that.
This is very simple example, And may not create a problem as you are creating InputStream in same bloke. But if InputStream is closed because of some Exception or other fault, in that case your code will fail, So its always better to check if InputStream is available
The second one will not compile since the constructor of FileInputStream can throw a FileNotFoundException, thus you'd need an extra try-catch block, unless of course, the method itself throws it.
Another common idiom is to write a closeQuietly() method to avoid having to write the if (is != null) check all over your finally blocks. This is what Apache Common's IOUtils does:
public static void closeQuietly(InputStream input) {
try {
if (input != null) {
input.close();
}
} catch (IOException ioe) {
// ignore
}
}
Also note that since Java 7, you can use the following:
try (InputStream is = new FileInputStream(file)) {
} catch (final FileNotFoundException | IOException ex) {
}
The null check here for the InputStream is necessary as it is possible that the variable might not be assigned. In this case a NullPointerException would be thrown when attempting to close it when calling:
in.close();
In the 2nd block outside of the try/catch block:
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
You can easily encounter other exceptions before entering the block and the InputStream is never closed.
Lets say you need to open not one, but two files. You would do
final InputStream in = new FileInputStream(file1);
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
in.close();
}
If the out fails to open, you will get an exception and because it's out of the try block in won't be closed in the finally block.
In the other method:
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
if (out != null) out.close();
if (in != null) in.close();
}
If out fails to open, you will go to the finally block and close both streams. If in fails to open, you will go to the finally block, and free only in - because out==null.
edit
As the aetheria mentioned, that code wouldn't work because close() throws exception in Java. It can easily be fixed by putting each resource release in it's own try-catch block:
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
try{ out.close(); }catch(Exception e){}
try{ in.close(); }catch(Exception e){}
}
I ditched the null checking - if in or out is null, it'll throw a NullPointerException that will be ignored. And the reason I ignore close exceptions is that disposal methods shouldn't throw exceptions in the first place. If handling closing exceptions is required, you can always close the streams again, after the finally block. That way, any stream that can be closed will be closed already(so you wouldn't have to worry about it), and you can handle any exceptions from close more elegantly.
Now, aetheria also suggested to put a separate try-finally block for each resource that would look like this:
final InputStream in = new FileInputStream(file1);
try {
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
}
} finally {
in.close();
}
This works, but even with only two resources, it's much less elegant, as it splits the allocations and releasing code, making it harder to keep track of it(in my opinion, at least).

What might cause an IOException in Java when I make a call to Reader.read()?

I have code that looks something like:
public static void func(Reader r){
int c = r.read();
...
}
and the compiler tells me that r.read() might throw an IOException. Under what circumstances might this happen? It seems clear that something like FileNotFoundException is thrown when a file is not found, but an IOException is rather vague.
Edit:
In case it is of interest to anyone, I asked this question because I thought there must be a better way of handling the situation than just printStackTrace. However, without knowing what might cause the exception, I wasn't really sure how it should be done.
Lots of things can cause an IOException. When it gets thrown, you can print it out or check the message (Exception.getMessage()) to see what caused it.
A FileNotFoundException is a subclass of IOException, you can check the "known subclasses" list for others.
For example:
public void load(InputStream inputStream) throws IOException {
this.inputStream = inputStream;
this.properties.load(this.inputStream);
this.keys = this.properties.propertyNames();
inputStream.close();
}
I think that's when you have problem with input / output (connections) because of security or for example not opening the stream.
Code source: stackoverflow
It can throw an IOException when the either the stream itself is corrupted or some error occurred during reading the data i.e. Security Exceptions, Permission Denied etc and/or a set of Exceptions which are derived from IOEXception.
IOException is superclass of many exceptions like CharConversionException, CharacterCodingException and EOFException.
If the method listed all these exceptions then caller would have to catch all of them. So for convenience having IOException in throws clause helps callers to avoid multiple catch blocks. User can still handle specific exception if they desire so by checking for instance of or exception.getMessage().
If you want to know the specifics, in your catch block do this:
catch (IOException e)
{
e.printStackTrace();
}
This code will help you to debug and to see the IOException thrown:
String NL = System.getProperty("line.separator");
String line;
FileInputStream in;
try {
fileName = choose.getSelectedFile().getCanonicalPath();
} catch (IOException e) {
e.printStackTrace(); //This doesn't matter, see the second IOException catch.
}
try {
in = new FileInputStream(choose.getSelectedFile());
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
StringBuffer content=new StringBuffer("");
while((line = reader.readLine()) != null){
content.append(line+NL);
}
textArea.setText(content.toString());
reader.close();
reader.readLine();
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(new JFrame(), "The file does not exist!", "Error", JOptionPane.WARNING_MESSAGE);
} catch (IOException e) {
JOptionPane.showMessageDialog(new JFrame(), "There was an error in reading the file.", "Error", JOptionPane.WARNING_MESSAGE);
}
Good luck.

Assistance in writing my file writer method for a servlet

I have a simple servlet where I write to a file if it has a queryparameter 'hello', and since this is a test I want to display the error the the webpage also.
IntelliJ is complaining that I am not catching the IOException, not sure what's wrong:
private static void WriteToFile(String filePath, String fileName, String fileData) {
FileWriter writer = null;
try {
writer = new FileWriter(fileName);
writer.write(fileData);
} catch(IOException ex) {
} finally {
if(writer != null) {
writer.close();
}
}
}
Also, in my exception, I noticed on the web most people write:
How can I output the error to the web page?
You're not catching IOException when you call writer.close(); in the finally block.
You're also completely swallowing any IOException thrown in the main code, which is a really bad idea. If something's goes wrong, you'll have no idea what's happening.
I would personally suggest that you let that method throw the exception to the caller:
private static void writeToFile(String filePath, String fileName,
String fileData) throws IOException {
FileWriter writer = new FileWriter(fileName);
try {
writer.write(fileData);
} finally {
writer.close();
}
}
Note that if the try block throws an exception and the finally block does, you'll effectively "lose" the original exception. You may want to suppress exceptions throw when closing.
Or just use Guava which makes all of this simpler anyway with its Files class.
Or if you're using Java 7, you could use a try-with-resources statement.
(I note that you're ignoring filePath by the way - why?)
You can write in catch block too : writer.write(errorMessage);
or you may redirect to Error page if error occured

Categories