Stream not closed if IOException thrown while creating parser
See original GitHub issuev2.12.4
Hi, I’ve noticed that, ObjectMapper#readValue(URL src, Class<T> valueType)
, for example, will not close the stream if reading from the URL causes, say, a FileNotFoundException
. The exception is thrown in the createParser invocation, and so it is not caught by the _readMapAndClose
call. I’m able to verify this by creating many instances to a URL that returns a 200—in these cases, netstat
shows only one connection to the server. In the case of a URL returning a 404, there are many requests sitting in ESTABLISHED
, and then proceed to hang in CLOSE_WAIT
.
java.io.FileNotFoundException:
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1993)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1589)
at java.base/java.net.URL.openStream(URL.java:1161)
at com.fasterxml.jackson.core.TokenStreamFactory._optimizedStreamFromURL(TokenStreamFactory.java:211)
at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:1057)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3479)
at Main.main(Main.java:18)
Issue Analytics
- State:
- Created a year ago
- Comments:17 (11 by maintainers)
Top Results From Across the Web
How to solve: java.io.IOException: Stream closed
The solution to your problem is either make a copy of the stream, or don't consume it a second time after it has...
Read more >FilterInputStream (Java Platform SE 8 ) - Oracle Help Center
Creates a FilterInputStream by assigning the argument in to the field ... Throws: IOException - if the stream does not support seek, or...
Read more >Class Tika - Apache Tika
The given document stream is not closed by this method. Unlike in the parse(InputStream, Metadata) method, the given document metadata is not modified...
Read more >JsonReader (Gson 2.8.0 API) - Javadoc.io
To create a recursive descent parser for your own JSON streams, ... Throws: IOException - if the next token in the stream is...
Read more >Right way to Close InputStream and OutputStream in Java
Can you spot the error? Yes, output stream will not be closed if close() method of input stream will throw an Exception i.e....
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@cowtowncoder Thanks for the quick fix. I can confirm that the read-case via
File
is working correctly.@josh-byster I did a quick look at the initial issue and it seems to be an upstream issue in Java. Observed behavior with Java 17:
URLConnection
depending on the URL that cannot be closed (no close method).sun.net.www.protocol.http.HttpURLConnection
instance is created.URLConnection
is used to create the input stream viagetInputStream
.HttpURLConnection#getInputStream
is mostly a proxy forgetInputStream0
.getInputStream0
creates the input stream and assignes it to itself.FileNotFoundException
exception is thrown due to HTTP 404 but the input stream isn’t closed. See note *1.Actually, there is a way to close the internal input stream by calling
disconnect
of HttpURLConnection. With a bit of magic, all sockets are successfully closed (see example below). Unfortunately, we cannot use this workaround because it’s an internal Sun class.*1: AFAIK, the input stream is internally never closed but maybe I’m missing something. The code is mostly 15 years old and not well structured 😄 . The exception in HttpURLConnection seems to prevent the GC from freeing the
HttpURLConnection
instance that was created inURL#openStream
(maybe due to the input stream that is never closed).HttpURLConnection
most likely own the socket too.I just stepped though a few files but you could continue to locate the core issue if you like, or create an upstream issue. If you have this issue at work, my best bet is to report it to your “Java vendor” for prio support. Let me know, otherwise I’ll eventually report the potential bug.
Tested with:
Example using nodejs server from above:
I do not understand what you mean by this. Do you want to merge the issues?
The managed stream by Jackson is only closed after successfully initialization when
_readMapAndClose
is executed. In the error case, the exception occurs during initialization and the stream is leaked:JsonFactory#createParser(File f)
creates an input stream from the given file.ByteSourceJsonBootstrapper#constructParser
injackson.core
raise an IOException due to a failure indetectEncoding
(see stack trace above).UTF8StreamJsonParser
which should own the input stream, is never created and we never execute_readMapAndClose
.JsonFactory#createParser(File f)
is leaked because neither the initial method norUTF8StreamJsonParser
closes the stream.The same will most likely apply to
URL
as well.A simple solution would be to create the stream with try-with-resources and call
readValue(InputStream src, ...)
. Otherwise, catching the exception from_createParser
inJsonFactory#createParser
and closing the stream in an error case would work too. I’m a little bit lost about the ownership of the input stream in the latter case becauseByteSourceJsonBootstrapper
doesn’t own the stream at this moment.