2

How can I make sure that this method closes the OutputStream so a memory-leak won't happen?

public static void store(Properties properties, Class script) throws IOException {
    ScriptManifest scriptManifest = (ScriptManifest) script.getAnnotation(ScriptManifest.class);
    if (scriptManifest != null) {
        String name = scriptManifest.name();
        FileOutputStream outputStream = new FileOutputStream(Constants.SCRIPT_PROPERTIES_DIR + File.separator + name + ".properties");
        properties.store(outputStream, "");
        outputStream.close();
    } else {
        throw new RuntimeException("Script " + script.getName() + " does not have a ScriptManifest.");
    }
}
user2997204
  • 1,344
  • 2
  • 12
  • 24

2 Answers2

2

You can use try-with-resources. Example:

public static void store(Properties properties, Class script) throws IOException {
    ScriptManifest scriptManifest = (ScriptManifest) script.getAnnotation(ScriptManifest.class);
    if (scriptManifest != null) {
        String name = scriptManifest.name();
        try ( FileOutputStream outputStream = new FileOutputStream(Constants.SCRIPT_PROPERTIES_DIR + File.separator + name + ".properties") ) {
            properties.store(outputStream, "");
        }
    } else {
        throw new RuntimeException("Script " + script.getName() + " does not have a ScriptManifest.");
    }
}

or try with finally block like this:

public static void store(Properties properties, Class script) throws IOException {
    ScriptManifest scriptManifest = (ScriptManifest) script.getAnnotation(ScriptManifest.class);
    if (scriptManifest != null) {
        String name = scriptManifest.name();
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(Constants.SCRIPT_PROPERTIES_DIR + File.separator + name + ".properties");
            properties.store(outputStream, "");
        } finally {
            if ( outputStream != null ) outputStream.close();
        }
    } else {
        throw new RuntimeException("Script " + script.getName() + " does not have a ScriptManifest.");
    }
}
stjepano
  • 1,052
  • 7
  • 15
1

There are two approaches.

FileOutputStream outputStream = null;
try {
  outputStream = new FileOutputStream(...)
  ...
 }
 catch (IOException e) {
    throw new RuntimeException(...)
 }
 finally {
    // or use the Apache Commons IOUtils.closeQuietly(outputStream);
    // and then only need the one line
    if (outputStream != null) {
      try {
         outputStream.close();
      }
      catch (Exception ignore) { }
    }
 }

In later versions of Java, you can use the try-with-resources

try (FileOutputStream fos = new FileOutputStream("f:/tmp/stops.csv")) {
}
catch (IOException e) {
}
KevinO
  • 4,303
  • 4
  • 27
  • 36
  • is it possible to do this without removing the throws ....? – user2997204 Apr 02 '16 at 14:57
  • @user2997204, in either approach, you can still throw a different exception (from IOException) if desired. I made an edit in the first example to illustrate. – KevinO Apr 02 '16 at 15:02