Java Resource Leak - java

I have this code snippet in my application and I am quite sure that I have
closed all the streams.
But, surprisingly, I keep getting:
A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
java.lang.Throwable: Explicit termination method 'close' not called
Any pointers would be very useful.
if (fd != null) {
InputStream fileStream = new FileInputStream(fd.getFileDescriptor());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fileStream.read(buf)) != -1;) {
bos.write(buf, 0, readNum);
}
content = bos.toByteArray();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (fileStream != null) {
fileStream.close();
}
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

try moving the instantiation of the streams into the try
InputStream fileStream = null;
ByteArrayOutputStream bos = null;
byte[] buf = new byte[1024];
try {
fileStream = new FileInputStream(fd.getFileDescriptor());
bos = new ByteArrayOutputStream();

Try using try with resources. This eliminates the need to close resources in a finally block. https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
if (fd != null) {
byte[] buf = new byte[1024];
try (InputStream fileStream = new FileInputStream(fd.getFileDescriptor());
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
for (int readNum; (readNum = fileStream.read(buf)) != -1;) {
bos.write(buf, 0, readNum);
}
content = bos.toByteArray();
} catch (IOException ex) {
ex.printStackTrace();
}
}

Using try with resources would resolve the issue. https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html. You can have a look at AutoCloseable interface here which has been introduced in Java 7 http://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html

What I see, is that bos won't be closed if an Exception occurres while closing the fileStream.
And as stated before: Use the try-with-resources Statement:
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

Related

Resources should be closed - Sonar

I have the following piece of code:
public static byte[] readSomeFile(String filePath) {
byte[] buffer = new byte[FILE_SIZE];
FileInputStream fileIn = null;
BufferedInputStream buffIn = null;
DataInputStream inData = null;
int size = 0;
byte[] someArray= null;
try {
fileIn = new FileInputStream(filePath);
buffIn = new BufferedInputStream(fileIn);
inData = new DataInputStream(buffIn);
size = inData.read(buffer, 0, FILE_SIZE);
someArray= new byte[size];
System.arraycopy(buffer, 0, someArray, 0, size);
} catch (IOException e) {
//log(Log.ERROR,"IO ERROR: " + e.toString());
} finally {
try {
if (null != fileIn) {
fileIn.close();
}
if (null != buffIn) {
buffIn.close();
}
if (null != inData) {
inData.close();
}
} catch (Exception exFinally) {
// some stuff
someArray= null;
}
}
return someArray;
}
the problem is Sonar is still complaining about fileIn not being closed, although it's the first resource addressed in the finally block.
How does Sonar work in this case ? and how to resolve the Resources should be closed rule ?
If you have to use the Java 7 and above, I prefer you to use try with resources which was introduced in Java 7 new features.
Try-with-resources in Java 7 is a new exception handling mechanism that makes it easier to correctly close resources that are used within a try-catch block.
As to your code:
finally {
try {
if (null != fileIn) {
fileIn.close();
}
if (null != buffIn) {
buffIn.close();
}
if (null != inData) {
inData.close();
}
} catch (Exception exFinally) {
// some stuff
someArray= null;
}
}
Do you notice that ugly double try?
But, if you used the try with resources , close() is automatically called, if it throws an Exception or not, it will be supressed (as specified in the Java Language Specification 14.20.3) . Same happens for your case. I hope it helps.
So, your code will be looked like:
public static byte[] readSomeFile(String filePath) {
byte[] buffer = new byte[FILE_SIZE];
int size = 0;
byte[] someArray= null;
try (FileInputStream fileIn = new FileInputStream(filePath);
BufferedInputStream buffIn = new BufferedInputStream(fileIn);
DataInputStream inData = new DataInputStream(buffIn);) {
size = inData.read(buffer, 0, FILE_SIZE);
someArray= new byte[size];
System.arraycopy(buffer, 0, someArray, 0, size);
} catch (IOException e) {
//log(Log.ERROR,"IO ERROR: " + e.toString());
}
return someArray;
}

Efficient way to write InputStream to a File in Java 6

I will get input stream from third party library to my application.
I have to write this input stream to a file.
Following is the code snippet I tried:
private void writeDataToFile(Stub stub) {
OutputStream os = null;
InputStream inputStream = null;
try {
inputStream = stub.getStream();
os = new FileOutputStream("test.txt");
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
os.write(bytes, 0, read);
}
} catch (Exception e) {
log("Error while fetching data", e);
} finally {
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log("Error while closing input stream", e);
}
}
if(os != null) {
try {
os.close();
} catch (IOException e) {
log("Error while closing output stream", e);
}
}
}
}
Is there any better approach to do this ?
Since you are stuck with Java 6, do yourself a favour and use Guava and its Closer:
final Closer closer = Closer.create();
final InputStream in;
final OutputStream out;
final byte[] buf = new byte[32768]; // 32k
int bytesRead;
try {
in = closer.register(createInputStreamHere());
out = closer.register(new FileOutputStream(...));
while ((bytesRead = in.read(buf)) != -1)
out.write(buf, 0, bytesRead);
out.flush();
} finally {
closer.close();
}
Had you used Java 7, the solution would have been as simple as:
final Path destination = Paths.get("pathToYourFile");
try (
final InputStream in = createInputStreamHere();
) {
Files.copy(in, destination);
}
And yourInputStream would have been automatically closed for you as a "bonus"; Files would have handled destination all by itself.
If you're not on Java 7 and can't use fge's solution, you may want to wrap your OutputStream in a BufferedOutputStream
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream("xx.txt"));
Such buffered output stream will write bytes in blocks to the file, which is more efficient than writing byte per byte.
It can get cleaner with an OutputStreamWriter:
OutputStream outputStream = new FileOutputStream("output.txt");
Writer writer = new OutputStreamWriter(outputStream);
writer.write("data");
writer.close();
Instead of writing a string, you can use a Scanner on your inputStream
Scanner sc = new Scanner(inputStream);
while (sc.HasNext())
//read using scanner methods

Move file without using renameTo()

In my Java program, I would like to display the progress of moving a file. I use the following snippet of code to copy files, which allows me to track the bytes copied and shows it in a progress bar. I was wondering if the code code be adapted to move files rather than just copy them?
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile));
int theByte;
while((theByte = bis.read()) != -1)
{
bos.write(theByte);
}
bis.close();
bos.close();
Okay, so a "move" operation is a copy with a "delete" at the end, for example...
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(sourceFile));
bos = new BufferedOutputStream(new FileOutputStream(targetFile));
int theByte;
while((theByte = bis.read()) != -1)
{
bos.write(theByte);
}
bos.close();
bis.close();
// You may want to verify that the file's are the same (ie the file size for example)
if (!sourceFile.delete()) {
throw new IOException("Failed to remove source file " + sourceFile);
}
} catch (IOException exp) {
exp.printStackTrace();
} finally {
try {
bis.close();
} catch (Exception exp) {
}
try {
bos.close();
} catch (Exception exp) {
}
}

Downloading Large JSON File to local file using Java

I'm attempting to download a JSON from the following URL - http://api.crunchbase.com/v/1/companies.js - to a local file. I'm using Java 1.7 and the following JSON Libraries - http://www.json.org/java/ - to attempt to make it work.
Here's my code:
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(
new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1)
{
out.write(buffer, 0, numRead);
numWritten += numRead;
System.out.println(buffer.length);
System.out.println(" " + buffer.hashCode());
}
System.out.println(localFileName + "\t" + numWritten);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioe) {
}
}
}
When I run the code everything seems to work until midway through the loop the program seems to stop and not continue reading the JSON Object.
Does anyone know why this would stop reading? How could I fix the issue?
Try This:
public void saveUrl(String filename, String urlString) throws MalformedURLException, IOException
{
BufferedInputStream in = null;
FileOutputStream fout = null;
try
{
in = new BufferedInputStream(new URL(urlString).openStream());
fout = new FileOutputStream(filename);
byte data[] = new byte[1024];
int count;
while ((count = in.read(data, 0, 1024)) != -1)
{
fout.write(data, 0, count);
}
}
finally
{
if (in != null)
in.close();
if (fout != null)
fout.close();
}
}
Does anyone know why this would stop reading? How could I fix the issue?
I can't see anything obviously wrong with the client-side code. In the absence of any other evidence on the client side, I'd look at the server-side logs to see if there are any clues there.
IMO, the most likely explanation is one of the following:
There's a bug in the server-side code that is generating the JSON and it is crashing halfway through.
The server (or a proxy / reverse proxy) has a timeout on the time allowed for some part of the interaction, and this particular request is taking too long.

Problems reading a huge file of 12 MB (java.lang.OutOfMemoryError)

i need to open a file of 12 Megabytes, but actually i'm doing it creating a buffer of 12834566-byte, because the size of the file is 12MB and i am developing this app for Android mobile systems.
Then, i supose i have to read with blocks of 1024 Kbytes instead of one block of 12 Mbytes, with a for, but i don't know how to do it, i need a little help with it.
This is my actual code:
File f = new File(getCacheDir()+"/berlin.mp3");
if (!f.exists()) try {
InputStream is = getAssets().open("berlin.mp3");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
FileOutputStream fos = new FileOutputStream(f);
fos.write(buffer);
fos.close();
} catch (Exception e) { throw new RuntimeException(e); }
Please, can someone tell me what i have to changue in this code to read blocks of 1024 Kbytes instead of one block of 12 Mbytes?
THanks!
Try copying 1 KB at a time.
File f = new File(getCacheDir()+"/berlin.mp3");
if (!f.exists()) try {
byte[] buffer = new byte[1024];
InputStream is = getAssets().open("berlin.mp3");
FileOutputStream fos = new FileOutputStream(f);
int len;
while((len = is.read(buffer)) > 0)
fos.write(buffer, 0, len);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
IOUtils.close(is); // utility to close the stream properly.
IOUtils.close(fos);
}
Does Android support symbolic or hand links like UNIX? If it does, this would be faster/more efficient.
File f = new File(getCacheDir()+"/berlin.mp3");
InputStream is = null;
FileOutputStream fos = null;
if (!f.exists()) try {
is = getAssets().open("berlin.mp3");
fos = new FileOutputStream(f);
byte[] buffer = new byte[1024];
while (is.read(buffer) > 0) {
fos.write(buffer);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// proper stream closing
if (is != null) {
try { is.close(); } catch (Exception ignored) {} finally {
if (fos != null) {
try { fos.close(); } catch (Exception ignored2) {}
}
}
}
}
import org.apache.commons.fileupload.util.Streams;
InputStream in = getAssets().open("berlin.mp3");
OutputStream out = new FileOutputStream(f);
Streams.copy(in, out, true);

Categories