1

I use Jsoup to parse a file from a remote URL like the following:

Document doc = Jsoup.connect(urlString)
    .timeout(5000)
    .get();

If the website fails to respond within the timeout, a SocketTimeoutException is thrown, as expected. I also have StrictMode turned on to warn me about unclosed resources. At the timeout, StrictMode tells me that a resource was not closed:

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
        at dalvik.system.CloseGuard.open(CloseGuard.java:184)
        at java.io.FileInputStream.<init>(FileInputStream.java:80)
        at libcore.io.DiskLruCache.get(DiskLruCache.java:391)
        at libcore.net.http.HttpResponseCache.get(HttpResponseCache.java:98)
        at android.net.http.HttpResponseCache.get(HttpResponseCache.java:204)
        at libcore.net.http.HttpEngine.initResponseSource(HttpEngine.java:257)
        at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:218)
        at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)
        at org.jsoup.helper.HttpConnection$Response.a(SourceFile:439)
        at org.jsoup.helper.HttpConnection$Response.a(SourceFile:465)
        at org.jsoup.helper.HttpConnection$Response.a(SourceFile:424)
        at org.jsoup.helper.HttpConnection.execute(SourceFile:178)
        at org.jsoup.helper.HttpConnection.get(SourceFile:167)
        at com.example.$3.call(SourceFile:163)
        at a.e.run(SourceFile:198)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
        at java.lang.Thread.run(Thread.java:841)

I cannot see how to close the resource Jsoup creates. How would I do that?

Jon G
  • 1,656
  • 3
  • 16
  • 42

1 Answers1

0

Jsoup closes the connection after the request is done and in case of exception

as you can read in the source JSOUP HttpConnection

 static Response execute(Connection.Request req, Response previousResponse) throws IOException {
        Validate.notNull(req, "Request must not be null");
        String protocol = req.url().getProtocol();
        if (!protocol.equals("http") && !protocol.equals("https"))
            throw new MalformedURLException("Only http & https protocols supported");

        // set up the request for execution
        if (req.method() == Connection.Method.GET && req.data().size() > 0)
            serialiseRequestUrl(req); // appends query string
        HttpURLConnection conn = createConnection(req);
        Response res;
        try {
            conn.connect();
            if (req.method() == Connection.Method.POST)
                writePost(req.data(), conn.getOutputStream());

            int status = conn.getResponseCode();
            boolean needsRedirect = false;
            if (status != HttpURLConnection.HTTP_OK) {
                if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM || status == HttpURLConnection.HTTP_SEE_OTHER)
                    needsRedirect = true;
                else if (!req.ignoreHttpErrors())
                    throw new HttpStatusException("HTTP error fetching URL", status, req.url().toString());
            }
            res = new Response(previousResponse);
            res.setupFromConnection(conn, previousResponse);
            if (needsRedirect && req.followRedirects()) {
                req.method(Method.GET); // always redirect with a get. any data param from original req are dropped.
                req.data().clear();

                String location = res.header("Location");
                if (location != null && location.startsWith("http:/") && location.charAt(6) != '/') // fix broken Location: http:/temp/AAG_New/en/index.php
                    location = location.substring(6);
                req.url(new URL(req.url(), encodeUrl(location)));

                for (Map.Entry<String, String> cookie : res.cookies.entrySet()) { // add response cookies to request (for e.g. login posts)
                    req.cookie(cookie.getKey(), cookie.getValue());
                }
                return execute(req, res);
            }
            res.req = req;

            // check that we can handle the returned content type; if not, abort before fetching it
            String contentType = res.contentType();
            if (contentType != null && !req.ignoreContentType() && (!(contentType.startsWith("text/") || contentType.startsWith("application/xml") || contentType.startsWith("application/xhtml+xml"))))
                throw new UnsupportedMimeTypeException("Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml",
                        contentType, req.url().toString());

            InputStream bodyStream = null;
            InputStream dataStream = null;
            try {
                dataStream = conn.getErrorStream() != null ? conn.getErrorStream() : conn.getInputStream();
                bodyStream = res.hasHeader("Content-Encoding") && res.header("Content-Encoding").equalsIgnoreCase("gzip") ?
                        new BufferedInputStream(new GZIPInputStream(dataStream)) :
                        new BufferedInputStream(dataStream);

                res.byteData = DataUtil.readToByteBuffer(bodyStream, req.maxBodySize());
                res.charset = DataUtil.getCharsetFromContentType(res.contentType); // may be null, readInputStream deals with it
            } finally {
                if (bodyStream != null) bodyStream.close();
                if (dataStream != null) dataStream.close();
            }
        } finally {
            // per Java's documentation, this is not necessary, and precludes keepalives. However in practise,
            // connection errors will not be released quickly enough and can cause a too many open files error.
            conn.disconnect();
        }

        res.executed = true;
        return res;
    }

so i think it's not a problem.

GioLaq
  • 2,489
  • 21
  • 26