Jsoup — Закрытие не вызывается — Android StrictMode

Я использую Jsoup для анализа файла с удаленного URL-адреса следующим образом:

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

Если веб-сайт не отвечает в течение времени ожидания, выдается SocketTimeoutException, как и ожидалось. У меня также включен StrictMode, чтобы предупредить меня о незакрытых ресурсах. По тайм-ауту StrictMode сообщает мне, что ресурс не был закрыт:

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)

Я не вижу, как закрыть ресурс, который создает Jsoup. Как бы я это сделал?


person Jon G    schedule 17.09.2014    source источник


Ответы (1)


Jsoup закрывает соединение после выполнения запроса и в случае исключения

как вы можете прочитать в источнике 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;
    }

так что я думаю это не проблема.

person JoaoBiriba    schedule 17.09.2014
comment
Спасибо за информацию. Я предполагаю, что это должно быть ложное срабатывание от StrictMode. - person Jon G; 17.09.2014