我有以下代码(Android 4):
private HttpURLConnection conn = null;
private synchronized String downloadUrl(String myurl) {
InputStream is = null;
BufferedReader _bufferReader = null;
try {
URL url_service = new URL(.....);
System.setProperty("http.keepAlive", "false");
System.setProperty("http.maxConnections", "5");
conn = (HttpURLConnection) url_service.openConnection();
conn.setReadTimeout(DataHandler.TIME_OUT);
conn.setConnectTimeout(DataHandler.TIME_OUT);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("connection", "close");
conn.setInstanceFollowRedirects(false);
conn.connect();
StringBuilder total = null;
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
is = conn.getInputStream();
_bufferReader = new BufferedReader(new InputStreamReader(is));
total = new StringBuilder();
String line;
while ((line = _bufferReader.readLine()) != null) {
total.append(line);
}
} else {
onDomainError();
}
return total.toString();
} catch (SocketTimeoutException ste) {
onDomainError();
} catch (Exception e) {
onDomainError();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
}
}
if (_bufferReader != null) {
try {
_bufferReader.close();
} catch (Exception e) {
// TODO: handle exception
}
}
if (conn != null)
conn.disconnect();
conn = null;
}
return null;
}
使用了 .disconnect()
,keep-alive设置为false,最大连接数设置为5.但是,如果发生SocketTimeout
exception
,则连接未关闭且设备很快就会关闭记忆。这怎么可能?
此外,根据http://developer.android.com/reference/java/net/HttpURLConnection.html,HttpURLConnection
如果keep-alive设置为disconnect()
,则应关闭false
上的连接,并在keep-alive为{{1 }}。这些方法都不适合我。什么想法可能是错的?
答案 0 :(得分:0)
一种可能性是您没有尽快设置属性。根据javadoc,在发出任何HTTP请求之前,需要将“keepalive”属性设置为false 。在初始化URL协议驱动程序之前,这可能实际。
另一种可能性是你的OOME根本不是由此引起的。这可能是您的应用对其下载的内容所做的事情造成的。
您的代码也存在其他一些问题。
变量名url_service
,_bufferedReader
和myurl
都违反了Java的标识符命名约定。
conn
变量应该是局部变量。将其设为字段会使downloadUrl
方法不可重入。 (并且可能会导致您的问题...如果多个线程正在共享此对象的一个实例!)
您无需关闭缓冲的阅读器和输入流。只需关闭阅读器,它就会关闭流。这对读者来说可能无关紧要,但如果你为缓冲编写器执行此操作并且先关闭输出流,则可能会出现异常。
<强>更新强>
所以我们肯定有很多非垃圾HttpURLConnectionImpl
实例,我们可能有多个线程通过AsyncTask
运行此代码。
如果您尝试连接到不响应的站点(例如,TCP / IP连接请求是黑洞的那个站点......)那么conn.connect()
呼叫将长时间阻塞并最终抛出一个例外。如果连接超时足够长,并且您的代码并行执行这些调用的潜在无限数量,那么您可能会有很多这样的实例。
如果这个理论是正确的,那么你的问题与保持活动和连接没有被关闭无关。问题出在另一端......在第一个地方从未正确建立的连接会堵塞内存,每个连接都会占用一个线程/线程堆栈:
Executor
运行这些请求。请注意AsyncTask
javadoc中的内容:
“AsyncTask旨在成为Thread和Handler的辅助类,并不构成通用的线程框架。理想情况下,AsyncTasks应该用于短操作(最多几秒钟)。如果你需要保留线程运行很长一段时间,强烈建议您使用java.util.concurrent pacakge提供的各种API,例如Executor,ThreadPoolExecutor和FutureTask。“