微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

活动中的内存泄漏管理服务连接onResume / onPause

如何解决活动中的内存泄漏管理服务连接onResume / onPause

| 我已经在我的应用程序中发现了严重的内存泄漏问题,并在快速创建/销毁活动(或可能快速恢复/暂停;至少是我根据测试所考虑的问题)时管理与服务的连接。 我希望获得一些帮助,以了解造成此问题的原因以及如何正确修复它。 当我从另一个应用程序切换到我的应用程序,并且屏幕方向不同(并且我持有连接对象的活动不在前台)时,会发生这种情况。 我有一堆似乎无法被垃圾收集的活动,因为它们似乎仍被以下人员引用:  \'LoadedApk $ Servicedispatcher $ DeathMonitor \'对象位于GC根目录。 我在onResume()中调用bind,在onPause()中取消绑定。 经过一些实验后,我相信我以某种方式绑定/解除绑定的根本原因。例如,如果我停止调用unbind,则内存泄漏将停止,但会出现一些ConnectionLeaked异常(我了解它们的原因)。 也许在连接对象收到通知之前调用unbind会以某种方式导致此问题(但我在logcat中看不到错误,并且该服务正确接收了bind / unbind调用)。 当我使用Eclipse内存分析器时(在我的应用程序和另一个应用程序之间来回切换几次后),我看到许多活动实例具有以下到GC根目录的路径: 我的活动 <-mContext android.app.LoadedApk $ Servicedispatcher @ 0x41059d6 <----此$ 0 android.app.LoadedApk $ Servicedispatcher $ DeathMonitor @ 0x4105b548本机堆栈 我的源代码基本上是:
public class MyActivity extends Activity {
    private final String TAG = \"MyActivity\";
    public IREventService mREventService;
    private ServiceConnection mConnection = new ServiceConnection() {
        // Called when the connection with the service is established
        public void onServiceConnected(ComponentName className,IBinder service) {
            mREventService = IREventService.Stub.asInterface(service);
            Log.e(TAG,\"connected to service:\"+MyActivity.this.toString()+ \"connection: \"+this.toString());

        }

        // Called when the connection with the service disconnects unexpectedly
        public void onServicedisconnected(ComponentName className) {
            Log.e(TAG,\"Service has unexpectedly disconnected:\"+this.toString());
            mREventService = null;
        }
    };

    @Override
    protected void onResume() {
        super.onResume();
        Intent intent = new Intent(this,EventService.class);
        intent.setAction(this.toString());

        Log.w(TAG,\"bindService:\"+this.toString());
        bindService(intent,mConnection,Context.BIND_AUTO_CREATE);
    }


    @Override
    protected void onPause() {
        super.onPause();
        Log.w(TAG,\"unbinding from service:\"+this.toString());
        unbindService(mConnection);

    }


}
logcats日志看起来像:(EventService是服务,我正在登录onBind()和onUnBind())
<I switched to another app>
06-17 17:27:08.965: WARN/MyActivity(5987): MyActivity onStop()

<this is where i switch back to my app>
06-17 17:27:09.415: INFO/ActivityManager(154): Config changed: { scale=1.0 imsi=310/4 loc=en_US touch=3 keys=1/1/2 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=169}
06-17 17:29:44.855: WARN/MyActivity(5987): MyActivity onDestroy()
06-17 17:29:44.855: INFO/TabletStatusBar(205): disABLE_BACK: no
06-17 17:29:45.015: WARN/MyActivity(5987): MyActivity onCreate()
06-17 17:29:45.015: WARN/MyActivity(5987): MyActivity onResume()
06-17 17:29:45.015: WARN/MyActivity(5987): bindService:MyActivity@408753a0
06-17 17:29:45.015: WARN/EventService(6009): onBind() MyActivity@408753a0
06-17 17:29:45.025: WARN/MyActivity(5987): MyActivity onPause()
06-17 17:29:45.025: WARN/MyActivity(5987): unbinding from service:MyActivity@408753a0
06-17 17:29:45.025: WARN/EventService(6009): onUnBind() MyActivity@408753a0
06-17 17:29:45.025: ERROR/MyActivity(5987): connected to service:MyActivity@408753a0connection: com.yogiplay.apps.MyActivity$1@40878328
06-17 17:29:45.065: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 32K,3% free 31936K/32839K,paused 34ms
06-17 17:29:45.125: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 65K,4% free 32895K/33927K,paused 36ms
06-17 17:29:45.205: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 803K,5% free 33550K/35079K,paused 30ms
06-17 17:29:45.245: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 65K,4% free 34109K/35335K,paused 27ms
06-17 17:29:45.255: INFO/dalvikvm-heap(5987): Grow heap (frag case) to 36.976MB for 3722256-byte allocation
06-17 17:29:45.285: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed <1K,4% free 37744K/38983K,paused 25ms
06-17 17:29:45.335: DEBUG/dalvikvm(5987): GC_CONCURRENT freed <1K,paused 2ms+3ms
06-17 17:29:45.645: INFO/WindowManager(154): Setting rotation to 3,animFlags=1
06-17 17:29:45.665: INFO/ActivityManager(154): Config changed: { scale=1.0 imsi=310/4 loc=en_US touch=3 keys=1/1/2 nav=1/2 orien=P layout=0x10000014 uiMode=0x11 seq=170}
06-17 17:29:45.685: DEBUG/FlurryAgent(5770): Ending session
06-17 17:29:45.755: WARN/MyActivity(5987): MyActivity onStop()
06-17 17:29:45.755: WARN/MyActivity(5987): MyActivity onDestroy()
06-17 17:29:45.755: WARN/IInputConnectionWrapper(5770): showStatusIcon on inactive InputConnection
06-17 17:29:45.865: WARN/MyActivity(5987): MyActivity onCreate()
06-17 17:29:45.865: WARN/MyActivity(5987): MyActivity onResume()
06-17 17:29:45.865: WARN/MyActivity(5987): bindService:MyActivity@409e4c00
06-17 17:29:45.875: WARN/EventService(6009): onBind() MyActivity@409e4c00
06-17 17:29:45.875: WARN/MyActivity(5987): MyActivity onPause()
06-17 17:29:45.875: WARN/MyActivity(5987): unbinding from service:MyActivity@409e4c00
06-17 17:29:45.875: WARN/EventService(6009): onUnBind() MyActivity@409e4c00
06-17 17:29:45.875: ERROR/MyActivity(5987): connected to service:MyActivity@409e4c00connection: com.yogiplay.apps.MyActivity$1@409e4d20
06-17 17:29:45.925: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 6130K,18% free 32743K/39815K,paused 24ms
06-17 17:29:46.005: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 883K,16% free 33737K/39815K,paused 23ms
06-17 17:29:46.035: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 1K,15% free 33970K/39815K,paused 23ms
谢谢您的帮助。     

解决方法

        您似乎在ServiceConnection.onServiceConnected和Context.unbindService之间遇到了已知的Android 4.0之前的竞争状态。 在Android 4.0之前的版本上,如果在收到绑定服务的服务连接的ServiceConnection.onServiceConnected方法的调用之前调用Context.unbindService,则框架将通过以下方式泄漏对您的上下文的JNI引用android.app.LoadedApk $ ServiceDispatcher $ DeathMonitor对象。 很可能是您遇到了这个问题-如果您查看日志,则会看到在onConnected消息之前已打印onUnbind消息:
06-17 17:29:45.875: WARN/EventService(6009): onUnBind() MyActivity@409e4c00
06-17 17:29:45.875: ERROR/MyActivity(5987): connected to service:MyActivity@409e4c00connection: com.yogiplay.apps.MyActivity$1@409e4d20
此错误已为Android 4.0修复。这是修复该错误的提交: https://github.com/android/platform_frameworks_base/commit/5a6ef737edbf57577443ac056613afe6cb121519 对于较早版本的Android,一种解决方法是将对unbindService的调用延迟到收到ServiceConnection.onServiceConnected的调用之后。对于它的价值,可以从服务连接的onServiceConnected回调方法中调用Context.unbindService。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。