【问题标题】:Android JAVA - Service return OutOfMemoryError exception after some whileAndroid JAVA - 服务在一段时间后返回 OutOfMemoryError 异常
【发布时间】:2014-05-19 23:55:14
【问题描述】:

我正在开发我的第一个 Android 应用程序。我已经创建了一个服务类,其作用是检查外部网页上是否有任何新信息。 HTTP 请求和服务正常工作,但过了一会儿我得到了这些OutOfMemoryError

是否有人能够看到服务收集所有内存的位置?

错误信息 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)

错误消息 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)

我的服务等级。

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();
                }

            }
        });
    }

【问题讨论】:

    标签: java android out-of-memory threadpool


    【解决方案1】:

    每次计时器到期时,您的代码都会不断创建一个新的 AsyncHttpClient 对象!如果对象永远不会完成它的工作,那么在某些时候,你会耗尽内存。

    由于您只是定期检查更新,因此您应该将 AsyncHttpClient 对象设为静态并重复使用它。

    具体看http://loopj.com/android-async-http/,推荐用法部分。

    【讨论】:

    • 认为这样可以解决问题。我将尝试实现静态访问​​器,看看应用程序现在将如何处理内存。谢谢@iheanyi
    • 这可能是一个愚蠢的问题,但是当方法完成时,为什么 AsyncHttpClient 对象不被 Java 垃圾收集处理?
    • @boje - 因此,AsyncHttpClient 创建了一个运行自己的线程的对象。这允许它异步运行 - 即使您的代码正忙于做其他事情,它也会运行。如果您想要只有本地生命周期的东西,请改用 HttpClient 。因此,鉴于它会自行关闭并运行,您需要明确告诉它在完成后关闭或停止运行。由于您不这样做并且 AsyncHttpClient 线程仍在运行,因此垃圾收集器没有理由释放内存。
    • @boje 请记住,仅仅因为对 post() 的调用返回,并不意味着 post() 操作实际上已经完成(毕竟它是一个 AsyncHttpClient)。因此,作为用户,如果您希望释放内存,则需要显式关闭 AsyncHttpClient 对象。请注意,由于它在后台运行并且您使用的是静态实例,因此您应该只在终止服务时调用的方法中调用 close()。如果您想在此之前 close(),您应该检查任何挂起的操作是否已完成,或者 close() 了解挂起的操作可能未完成。
    猜你喜欢
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 1970-01-01
    相关资源
    最近更新 更多