I am writing a Java 7-compatible program in eclipse, and a part of the code I wrote says there is a memory leak. Here is my code:
FileChannel output1 =
-->new FileOutputStream(System.getProperty("user.home")+"\\Desktop\\file\\output\\data.bin")<--
.getChannel();
output1.write(fileFinal);
output1.close();
FileChannel output2 =
-->new FileOutputStream(System.getProperty("user.home")+"\\Desktop\\file\\output\\data0.bin")<--
.getChannel();
output2.write(fileFinal);
output2.close();
FileChannel output3 =
-->new FileOutputStream(System.getProperty("user.home")+"\\Desktop\\file\\output\\data1.bin")<--
.getChannel();
output3.write(fileFinal);
output3.close();
FileChannel output4 =
-->new FileOutputStream(System.getProperty("user.home")+"\\Desktop\\file\\output\\data2.bin")<--
.getChannel();
output4.write(fileFinal);
output4.close();
The parts between the arrows give me an error ("Resource leak: '(opencaret)unassigned Closeable value(closecaret)' is never closed"). Notice how I close data.bin (output1) and data0.bin through data2.bin (output2 through output4) immediately after writing them. What is happening here? Is it a false positive, or is there something more technical at play?
Note: I replaced the carets in the error with (opencaret) and (closecaret) because the message editor thinks it's HTML, and won't display the carets or their contents. I can understand why you guys would block HTML to begin with (malicious code injection), but there has to be a more elegant way to detect it without blocking anything between carets altogether.
I'm running eclipse 2019-06 (4.12.0) on Windows 10 Pro with JDK 1.8.0_221 and JRE 1.8.0_221 installed, and the project is using Java 1.7 compiler compliance (for compatibility with older Java installations, since some systems that run this may only be able to run .jars as applets in the browser, and most browsers disabled NPAPI plugin support, and thereby prevented Java browser plugin updates).
Edit: I finally got my program working. This is the working code:
try (FileOutputStream fos1 = new FileOutputStream(System.getProperty("user.home")+"\\Desktop\\file\\output\\data.bin");
FileChannel output1 = fos1.getChannel())
{
output1.write(fileFinal);
output1.close();
}
catch (IOException i)
{
}
fileFinal.position(0);
try (FileOutputStream fos2 = new FileOutputStream(System.getProperty("user.home")+"\\Desktop\\file\\output\\data0.bin");
FileChannel output2 = fos2.getChannel())
{
output2.write(fileFinal);
output2.close();
}
catch (IOException j)
{
}
fileFinal.position(0);
try (FileOutputStream fos3 = new FileOutputStream(System.getProperty("user.home")+"\\Desktop\\file\\output\\data1.bin");
FileChannel output3 = fos3.getChannel())
{
output3.write(fileFinal);
output3.close();
}
catch (IOException k)
{
}
fileFinal.position(0);
try (FileOutputStream fos4 = new FileOutputStream(System.getProperty("user.home")+"\\Desktop\\file\\output\\data2.bin");
FileChannel output4 = fos4.getChannel())
{
output4.write(fileFinal);
output4.close();
}
catch (IOException l)
{
}
Thanks to @holger for the fix.
While you thought of the normal case, you also have to worry what happens when there is an exception writing the file contents
It is possible to open an file without error, and then while writing get an "ioException: out of disk space"
To handle closing in these situations, it's the best to use a try with resources:
try (FileChannel output1 = new FileOutputStream(System.getProperty("user.home")+"\\Desktop\\file\\output\\data0.bin") .getChannel()) {
output2.write(fileFinal);
}