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. Как бы я это сделал?
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;
}
так что я думаю, что это не проблема.