Resources closed but sonarlint still showing resource not closed - java

I have defined Output stream like below
OutputStream os=new FileOutputStream(file);
Tried to close the resource like below
if(os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}}
Still sonarlint showing "Use try-with-resources or close this "FileOutputStream" in a "finally" clause."

If you are doing the operations in the same method it's important to put the close in a finally statement of a try that envolves the open part of the stream. This ensures that in case of failure (Exception) the stream is allways closed if required
Bad sonar code:
OutputStream os=new FileOutputStream(file);
... // your code operations with os
// If something is going really bad here and ends in exception the
// stream will never be closed
if(os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Better code:
OutputStream os = null;
try{
os = new FileOutputStream(file);
... // your code operations with os
} finally{
// The stream is allways closed at the end of the method execution
if(os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The best code (in case of Java 1.7 or upper)
try (OutputStream os = new FileOutputStream(file)){
... // your code operations with os
// The stream is allways closed at the end of the try block
}

Try this instead. You do not do a close when using try with resources, that is automatically handled... i.e.
"The try-with-resources statement ensures that each resource is closed
at the end of the statement."
try( OutputStream os=new FileOutputStream(file) ) {
....
}
Any resources declared within the brackets are closed automatically once the program flow has completed whether an exception is thrown or not..
Examples here : https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

Related

Potnetial Resource Leak with IOUtils Persists like a Stubborn Mule

I'm using IOUtils to parse JSON from a HttpServletRequest request:
baseRequest.setAuthentication(null);
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
PrintWriter writerResponse = response.getWriter();
-> String data = IOUtils.toString(request.getInputStream(), "UTF-8"); <-
But Eclipse complains of a potential resource leak:
Potential resource leak: '<unassigned Closeable value>' may not be closed
Even when I surround it with a try/finally block and close via IOUtils.closeQuietly() the error persists like a stubborn mule.
String data = "";
try {
data = IOUtils.toString(request.getInputStream(), "UTF-8");
} catch (IOException e) {
} finally {
IOUtils.closeQuietly(request.getInputStream());
}
What is causing this error and how do I fix it?
P.S
While the code below:
try {
String data = IOUtils.toString(request.getInputStream(), "UTF-8");
} catch (IOException e) {
} finally {
IOUtils.closeQuietly(request.getInputStream());
}
does not throw any error, as soon as I try using the value 'data' anywhere in my code (even in the try statement) the error shows up again.
The error is correct. getInputStream may well return a new input stream each time you call getInputStream, so closing a new input stream doesn't help.
Save the input stream in a variable. Best of all, use try-with-resources:
try (InputStream stream = request.getInputStream()) {
data = IOUtils.toString(stream, "UTF-8");
}

Right place to flush the object

I have written a small piece of code for printing:
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(FileDescriptor.out), "ASCII"), 512);
out.write(msg + '\n');
out.flush();
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(
"Test failed ",
e);
} catch (IOException e) {
throw new IllegalStateException(
"Test failed", e);
} finally {
if (out != null) {
out = null;
}
}
Flushing of obj is done in the try block only. So is it a good way to do it or should I flush the object in the finally block?
Use modern syntax if you can and don't worry about all that. Closing will automatically flush it, so just use the try-with-resources syntax. This code is much shorter and more readable:
try(BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(FileDescriptor.out), "ASCII"), 512)) {
out.write(msg + '\n');
} catch (UnsupportedEncodingException | IOException e) {
logger.info("Test failed due to exception.");
throw new IllegalStateException("Test failed", e);
}
See more about try-with-resources if you are unfamiliar with the syntax.
The answer is "it depends." When do you want the text to be available for reading? If you don't need any of the text to be available for reading (i.e. no other process is actively waiting for on the stream as input), then you don't need to flush the stream until you are done with it (in the finally block). But you don't even need to explicitly do this since closing the stream automatically flushes it.
If another process is waiting on the stream, then you should flush whenever you want that output available to the other process. Flushing too often negates the benefits of buffering, however.
As others have noted, flushing and closing a stream can also throw an exception, so these actions should also be in their own try/catch block (a static utility method can be helpful for reducing the amount of boilerplate code when working with streams).

Using finally keyword on InputStream#close()

Basically I am not really sure what is the correct usage of the finally keyword, I only know the textual definition: Guarantees a code will be executed cause sometimes it doesn't. So I was hoping I could get some directions on this particular code:
Also if the try-catch block to call InputStream#close() is unnecesary
try {
inputStream = entity.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
String line = null;
while((line = br.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
responseText = sb.toString();
} catch(IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
You can also use a try-with-resources.
Like so:
try (YourResource resource) {
//Todo...
} catch(YourSpecificException ex) {
//Todo...
}
Your resource declared between parantheses will be automatically closed upon exiting the construction.
You can even declare multiple resources in one go, separate them with a semi-colon. It's all in the above link, really.
The finally block will always be executed whether the exception has arise from try block or not.So finally block is used as post activity.In the code you are using to close the stream.
the finally block ensures that no matter what happens during your try( success or exception), it will always run. This is normally used when cleaning up resources, like InputStream or a Socket
The try with resource paradigm cleans this up, but automatically closing things that are Closeable
try( InputStream inputStream = entity.getContent() )
{
}catch(Exception e)
{
}//declared resource in try automatically closed
http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
When try block is executing any exception that occurs will transfer the execution to the catch block then to finally block however if no exception happens in the try the execution of the code will continue after the try to the finally block, here in your code you are trying to use IO resource, which might throws an IO exception if it cannot be occupied by the process then no reference will be assigned to inputStream a finally block must be found to close the IO connection at any case if the resource was occupied or if it is null then nothing, remember finally will always be executed at any case, it is best for closing connection to databases and other resources to release memory too sometimes.
The times I've used finally are generally...
resource handling (IO, DB connections, sockets)
Concurrency (lock releasing, guaranteed counter changes)
finalization (try { } finally { super.finalize(); })
record keeping of states
try {
// Here the guarded area starts
// Here the guarded area ends
} catch {
// This block is executed when an exception occurs inside the guarded area
} finally {
// This block is executed always before leaving try - catch - finally block
// If there is an exception, then first catch block is executed and then finally
}
The code inside finally block you have is a commonly used structure for closing streams. If a stream was created inside guarded area (inputStream != null), then finally block will close it. If there was an exception before inputStream was created, then finally block is executed, but because inputStream == null, the code inside if statement does not execute.

Does IOUtils.copy block until writing is finished?

Here's my situation: I'm using IOUtils to copy a file. The next thing I do is send a JSON message to another program to say, "You can download the copy". The problem is about 25% of the time the other program gets an error saying "Received unexpected EOF downloading artifact".
Every time this error occurs, if I try again manually, the error doesn't occur. My theory is that IOUtils.copy doesn't block and the OS is still writing the file to the FS while the other program tries to download it. Is there a way to force IOUtils.copy or other functionally equivalent code to block until the OS has finished writing the file? Or is my theory incorrect? Here's the code I'm using:
private boolean archiveArtifact(String archivePath, String deployId, Artifact artifact) {
InputStream inputStream = null;
FileOutputStream fileOutputStream = null;
boolean successful = true;
try {
File archiveDir = new File(archivePath);
File deployDir = new File(archiveDir, deployId);
if (!deployDir.exists()) {
deployDir.mkdirs();
}
URLConnection connection = new URL(artifact.getJenkinsUrl()).openConnection();
inputStream = connection.getInputStream();
File output = new File(deployDir, artifact.getFileName());
fileOutputStream = new FileOutputStream(output);
IOUtils.copy(inputStream, fileOutputStream);
} catch (IOException e) {
successful = false;
logger.error(e.getMessage(), e);
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
successful = false;
logger.error(e.getMessage(), e);
}
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
successful = false;
logger.error(e.getMessage(), e);
}
}
return successful;
}
It might be worth noting that I'm copying this to a NFS. Keep in mind I don't really know anything about NFS. This is CentOS release 5.9 (Final).
Your current code only ensures that the file content is passed to the operating system for writing; it does not guarantee that it is actually written to a the disk.
To be certain that the file is actually written to disk you can call sync() on the FileDescriptor:
fileOutputStream.flush();
fileOutputStream.getFD().sync();

Closing URLConnection and InputStream correctly?

I've seen many different examples of using HttpURLConnection + InputStream, and closing them (or not closing them) after use. This is what I came up with to make sure everything is closed after finished, whether there's an error or not. Is this valid?:
HttpURLConnection conn = null;
InputStream is = null;
try {
URL url = new URL("http://example.com");
// (set connection and read timeouts on the connection)
conn = (HttpURLConnection)url.openConnection();
is = new BufferedInputStream(conn.getInputStream());
doSomethingWithInputStream(is);
} catch (Exception ex) {
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
if (conn != null) {
conn.disconnect();
}
}
Thanks
Yep.. Doing the end part in finally would be best idea because if code fails somewhere, program won't reach till .close(), .disconnect() statements that we keep before catch statements...
If the code fails somewhere and exception is thrown in between of the program, still finally get executed regardless of exception thrown...
There is also the new (with Java 7) 'try()' technique
try (OutputStream os = http.getOutputStream()) {
os.write(out);
}
Basically, it will auto-close anything in the try() statement, regardless of whether it is successful or not.

Categories

Resources