0

I want to fetch an HTML page and read in with BufferedReader. So I use try-with-resources to open it handles IOException this way:

try(BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
        
    } catch(IOException e) {
        throw e;
    }

Is this a good pattern to catch and instantly throw? And what if I omit try at all and state that function throws IOException? If then any potentional memory leak? Much appreciate any advice!

floatfoo
  • 83
  • 2
  • 8
  • 2
    You can remove the `catch(IOException e) { throw e; }` part if you don't want to handle potential IOException here and want it to propagate from your method. Just don't forget to add `throws IOException` in method declaration (but you should already have it, otherwise `throw e;` wouldn't compile). – Pshemo Jul 30 '22 at 19:34

2 Answers2

6

A catch block is not required in a try-with-resources statement. You could write the following, which would mean exactly the same as your original code:

try (BufferedReader reader = new BufferedReader(
        new InputStreamReader(url.openStream()))) {
    // do something
}

So, you can leave out the catch block, if all you ever do there is immediately throw the same exception again.

You do want the try block however, so that the BufferedReader and underlying stream(s) are automatically closed at the end of the block.

Is this a good pattern to catch and instantly throw?

No, catching and immediately re-throwing the same exception does not add anything useful.

Jesper
  • 202,709
  • 46
  • 318
  • 350
  • 1
    In C# at least, what the OP is doing is a bad practice because it would change the stack trace. Can you refresh my memory if that's the case for Java too? – EJoshuaS - Stand with Ukraine Jul 30 '22 at 20:07
  • Yes it is the case. I typically catch then log before re-throwing with a general purpose exception that's caught further up the stack. My general purpose exception has a method where I set whether it has already been logged so that when it's caught further up it can check whether it has been logged already and then log it there only if it hasn't been logged yet. – George Jul 30 '22 at 23:20
  • 2
    In Java, `Throwable` captures the stack when it is created. – Johannes Kuhn Jul 31 '22 at 14:09
1

To add to @Jesper's excellent answer, you do want to include the try block so that the BufferedReader will be closed right away. If you don't do this, it'll eventually be closed when the object is garbage collected, so it isn't technically a resource leak in the sense that the resources would eventually be reclaimed; however, the "eventually" part is potentially problematic because there are no guarantees as to exactly when that'll happen. Thus, a bigger issue is whether this would create race conditions if it's using a resource that needs to be reused eventually.

I'm not very familiar with the implementation details of that exact class, so this is somewhat speculative, but one example of an issue you can run into with some classes that perform network calls if you fail to return resources to the operating system promptly is port exhaustion.

By way of another example, if you are modifying a file, the file could remain locked until the GC happens to release the file lock by cleaning up the relevant object.