Android's memory leak because of HttpClient
sorry for my English.
I'm developing an Android application, consisting in various activities and a service which is activated by "main" activity. The service checks every 3 seconds (this interval is arbitrary) about active network connections into mobile phone. If there's a connection to a PC inside my local network, I then make a call to a web server there.
The problem is, I try to reach host PC through this function:
public boolean checkNet() {
HttpClient client;
HttpPost postMethod;
HttpParams httpParams;
URI uri;
try {
uri = new URI(Const.HOST_ADDRESS);
postMethod = new HttpPost(uri);
postMethod.addHeader("Content-Type", "text/xml");
httpParams = postMethod.getParams();
HttpConnectionParams.setSoTimeout(httpParams, 1000);
HttpConnectionParams.setSocketBufferSize(httpParams, 512);
HttpConnectionParams.setStaleCheckingEnabled(httpParams, false);
HttpConnectionParams.setCon开发者_如何学GonectionTimeout(httpParams, 1000);
client = new DefaultHttpClient();
}
catch (URISyntaxException use) {}
try
{
client.execute(postMethod);
return true;
}
catch (ClientProtocolException cpe) {
}
catch (IOException e) {
}
return false;
}
I do use this method, instead of checking WifiManager's and internal Android methods, because I have a situation like this: I can be connected to an open-encryption AP, but it has a login system (coova). Here, I can be associated (and have an IP inside LAN), but if I'm not logged I won't have access to any network, so I have to implement a "network-checking-wrapper".
So, if there was an exception in execute function because my host PC isn't reachable, DDMS will show me how heap size and allocation size will grow without control. I suspect that it's because of the sub-calls inside "execute" don't properly close obsolete references... for instance, here's a example of allocation tracker:
java.lang.AbstractStringBuilder enlargeBuffer AbstractStringBuilder.java 99 false
java.lang.AbstractStringBuilder append0 AbstractStringBuilder.java 170 false
java.lang.StringBuilder append StringBuilder.java 224 false
org.apache.http.conn.HttpHostConnectException <init> HttpHostConnectException.java 48 false
org.apache.http.impl.conn.DefaultClientConnectionOperator openConnection DefaultClientConnectionOperator.java 133 false
org.apache.http.impl.conn.AbstractPoolEntry open AbstractPoolEntry.java 164 false
org.apache.http.impl.conn.AbstractPooledConnAdapter open AbstractPooledConnAdapter.java 119 false
org.apache.http.impl.client.DefaultRequestDirector execute DefaultRequestDirector.java 348 false
Thanks in advance.
Well I've already noticed one problem. You have 2 separate try-catch blocks. The first one catches a URISyntaxException. You then, in your second try-catch, call client.execute(). But if there's an exception in your first catch, client may not be instantiated and your second try-catch will result in an NPE.
You should close the client connection by calling client.getConnectionManager().shutdown() in a finally-Block.
Your code becomes:
public boolean checkNet() {
HttpClient client = null;
HttpPost postMethod;
HttpParams httpParams;
URI uri;
boolean result = false;
try {
uri = new URI(Const.HOST_ADDRESS);
postMethod = new HttpPost(uri);
postMethod.addHeader("Content-Type", "text/xml");
httpParams = postMethod.getParams();
HttpConnectionParams.setSoTimeout(httpParams, 1000);
HttpConnectionParams.setSocketBufferSize(httpParams, 512);
HttpConnectionParams.setStaleCheckingEnabled(httpParams, false);
HttpConnectionParams.setConnectionTimeout(httpParams, 1000);
client = new DefaultHttpClient();
client.execute(postMethod);
result = true;
} catch (URISyntaxException use) {
} catch (ClientProtocolException cpe) {
} catch (IOException e) {
} finally {
if (client != null && client.getConnectionManager() != null) {
client.getConnectionManager().shutdown();
client = null;
}
}
return result;
}
精彩评论