问题
I am developing my first android app. I have been created a Service class which role is to check if any new information on an external webpage. The HTTP request and service work as i should, but after a while I get these OutOfMemoryError
.
Are someone able to see where the Service gather all that memory?
Error message 1.
java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes) failed: Try again
at java.lang.VMThread.create(Native Method)
at java.lang.Thread.start(Thread.java:1029)
at org.apache.http.impl.conn.tsccm.AbstractConnPool.enableConnectionGC(AbstractConnPool.java:140)
at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.createConnectionPool(ThreadSafeClientConnManager.java:120)
at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.(ThreadSafeClientConnManager.java:98)
at com.loopj.android.http.AsyncHttpClient.(AsyncHttpClient.java:210)
at com.loopj.android.http.AsyncHttpClient.(AsyncHttpClient.java:149)
at com.loopj.android.http.AsyncHttpClient.(AsyncHttpClient.java:119)
at com.quickit.app.MyService.checkUpdates(MyService.java:89)
at com.quickit.app.MyService.access$1(MyService.java:75)
at com.quickit.app.MyService$TimeDisplayTimerTask$1.run(MyService.java:68)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5105)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
at dalvik.system.NativeStart.main(Native Method)
Error message 2.
java.lang.OutOfMemoryError: thread creation failed
at java.lang.VMThread.create(Native Method)
at java.lang.Thread.start(Thread.java:1050)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:913)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1295)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:81)
at com.loopj.android.http.AsyncHttpClient.sendRequest(AsyncHttpClient.java:893)
at com.loopj.android.http.AsyncHttpClient.post(AsyncHttpClient.java:688)
at com.loopj.android.http.AsyncHttpClient.post(AsyncHttpClient.java:671)
at com.loopj.android.http.AsyncHttpClient.post(AsyncHttpClient.java:658)
at com.quickit.app.MyService.checkUpdates(MyService.java:90)
at com.quickit.app.MyService.access$1(MyService.java:75)
at com.quickit.app.MyService$TimeDisplayTimerTask$1.run(MyService.java:68)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:5092)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:564)
at dalvik.system.NativeStart.main(Native Method)
My service class.
public class MyService extends Service {
boolean login = false;
// constant
public static final long NOTIFY_INTERVAL = 10 * 1000; // 10 seconds
String address = Utilities.getAPIUrl();
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
SharedPreferences prefs = getSharedPreferences("com.quickit.app", Context.MODE_PRIVATE);
login = prefs.getBoolean("login", false);
// cancel if already existed
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
public class TimeDisplayTimerTask extends TimerTask {
@Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
@Override
public void run() {
if(login) {
checkUpdates();
}
}
});
}
}
private void checkUpdates() {
final SharedPreferences prefs = getSharedPreferences("com.quickit.app", Context.MODE_PRIVATE);
final String from_id = prefs.getInt("user", 0)+"";
final String lastCheck = prefs.getString("last_check", "0");
RequestParams params = new RequestParams();
params.put("type", "get_ask_questions");
params.put("fromid", from_id);
params.put("last_check", lastCheck);
AsyncHttpClient client = new AsyncHttpClient();
client.post(address, params, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(String response) {
try {
notification(response);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
回答1:
Your code is constantly creating a new AsyncHttpClient object every time that timer expires! If the object never finishes its work, at some point, you will run out of memory.
Since you are just periodically checking for updates, you should make the AsyncHttpClient object static and just reuse it.
Look at http://loopj.com/android-async-http/ specifically, the Recommended Usage section.
来源:https://stackoverflow.com/questions/22917511/android-java-service-return-outofmemoryerror-exception-after-some-while