2016-12-14 4 views
0

У меня есть служба, которая должна быть сохранена до тех пор, пока приложение активно. Поэтому в LoginActivity, когда пользователь не вошел в систему, я вызываю stopService, и когда пользователь входит в систему, я запускаю службу, явно просматривая startService.Обнаружена утечка службы до onDestroy

public class LoginActivity extends BaseActivity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_login); 

     if (accountHelper.isLoggedIn()) { 
      proceedToMainActivity(); 
     } else if (savedInstanceState == null) { 
      Fragment fragment = LoginFragment.newInstance(); 
      getSupportFragmentManager() 
        .beginTransaction() 
        .add(R.id.LoginContainer, fragment) 
        .commit(); 
     } 
    } 

    public void proceedToMainActivity() { 
     final Intent intent = MainActivity.createIntent(this); 
     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 
     startActivity(intent); 
    } 
//... 
} 

Тогда в других мероприятиях, я связываю в OnStart и отвязать в OnStop, в службе:

@Override 
public boolean onUnbind(Intent intent) { 
    Timber.d("onUnbind: %s", intent); 
    handler.scheduleStop(KEEP_ALIVE); 
    return false; 
} 

Это расписание stopSelf() после keep_alive времени (на данный момент его 500 (полсекунды), но это было нормально для 60000 (одна минута)
Служба уничтожена, когда пользователь уходит из приложения на долгое время и воссоздается успешно, однако после очень короткого времени от onCreate и onBind LeakCanary сообщает об утечке памяти этой службы. Обратите внимание, что ни onUnbind, ни onDestroy не вызывались. LeakCanary дает следующую свалку:

In <app-package>:1.0:7. 
* <app-package>.service.SocketService has leaked: 
* GC ROOT static android.app.ActivityThread.sCurrentActivityThread 
* references android.app.ActivityThread.mServices 
* references android.util.ArrayMap.mArray 
* references array java.lang.Object[].[1] 
* leaks <app-package>.service.SocketService instance 
* Retaining: 9.6 KB. 
* Reference Key: 525376d3-87b7-4522-9c9a-2d4547bc4f8d 
* Device: unknown Android Android SDK built for x86_64 sdk_google_phone_x86_64 
* Android Version: 7.1 API: 25 LeakCanary: 1.5 00f37f5 
* Durations: watch=5900ms, gc=126ms, heap dump=5628ms, analysis=22007ms 
* Details: 
* Class android.app.ActivityThread 
| static DEBUG_BACKUP = false 
| static sPackageManager = [email protected] (0x2ac01350) 
| static LOG_AM_ON_STOP_CALLED = 30049 
| static MIN_TIME_BETWEEN_GCS = 5000 
| static DEBUG_MESSAGES = false 
| static $classOverhead = byte[719]@1885346289 (0x706019f1) 
| static SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003 
| static sCurrentBroadcastIntent = [email protected] (0x70593368) 
| static HEAP_COLUMN = [email protected] (0x706d4d98) 
| static SERVICE_DONE_EXECUTING_ANON = 0 
| static ACTIVITY_THREAD_CHECKIN_VERSION = 4 
| static DEBUG_ORDER = false 
| static TWO_COUNT_COLUMNS = [email protected] (0x706d4e90) 
| static DEBUG_PROVIDER = false 
| static TAG = [email protected] (0x706e41d8) 
| static DEBUG_CONFIGURATION = false 
| static DEBUG_MEMORY_TRIM = false 
| static SERVICE_DONE_EXECUTING_STOP = 2 
| static DEBUG_SERVICE = false 
| static DEBUG_BROADCAST = false 
| static HEAP_FULL_COLUMN = [email protected] (0x706d4de8) 
| static localLOGV = false 
| static sMainThreadHandler = [email protected] (0x2ac02080) 
| static THUMBNAIL_FORMAT = [email protected] (0x70593350) 
| static REPORT_TO_ACTIVITY = true 
| static DEBUG_RESULTS = false 
| static DONT_REPORT = 2 
| static ONE_COUNT_COLUMN_HEADER = [email protected] (0x706d4ec8) 
| static SERVICE_DONE_EXECUTING_START = 1 
| static sCurrentActivityThread = [email protected] (0x2ac04100) 
| static USER_LEAVING = 1 
| static LOG_AM_ON_PAUSE_CALLED = 30021 
| static ONE_COUNT_COLUMN = [email protected] (0x706d4e70) 
| static LOG_AM_ON_RESUME_CALLED = 30022 
* Instance of android.app.ActivityThread 
| static DEBUG_BACKUP = false 
| static sPackageManager = [email protected] (0x2ac01350) 
| static LOG_AM_ON_STOP_CALLED = 30049 
| static MIN_TIME_BETWEEN_GCS = 5000 
| static DEBUG_MESSAGES = false 
| static $classOverhead = byte[719]@1885346289 (0x706019f1) 
| static SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003 
| static sCurrentBroadcastIntent = [email protected] (0x70593368) 
| static HEAP_COLUMN = [email protected] (0x706d4d98) 
| static SERVICE_DONE_EXECUTING_ANON = 0 
| static ACTIVITY_THREAD_CHECKIN_VERSION = 4 
| static DEBUG_ORDER = false 
| static TWO_COUNT_COLUMNS = [email protected] (0x706d4e90) 
| static DEBUG_PROVIDER = false 
| static TAG = [email protected] (0x706e41d8) 
| static DEBUG_CONFIGURATION = false 
| static DEBUG_MEMORY_TRIM = false 
| static SERVICE_DONE_EXECUTING_STOP = 2 
| static DEBUG_SERVICE = false 
| static DEBUG_BROADCAST = false 
| static HEAP_FULL_COLUMN = [email protected] (0x706d4de8) 
| static localLOGV = false 
| static sMainThreadHandler = [email protected] (0x2ac02080) 
| static THUMBNAIL_FORMAT = [email protected] (0x70593350) 
| static REPORT_TO_ACTIVITY = true 
| static DEBUG_RESULTS = false 
| static DONT_REPORT = 2 
| static ONE_COUNT_COLUMN_HEADER = [email protected] (0x706d4ec8) 
| static SERVICE_DONE_EXECUTING_START = 1 
| static sCurrentActivityThread = [email protected] (0x2ac04100) 
| static USER_LEAVING = 1 
| static LOG_AM_ON_PAUSE_CALLED = 30021 
| static ONE_COUNT_COLUMN = [email protected] (0x706d4e70) 
| static LOG_AM_ON_RESUME_CALLED = 30022 
| mActivities = [email protected] (0x2acf1e20) 
| mAllApplications = [email protected] (0x2acf60b8) 
| mAppThread = [email protected] (0x2ac02280) 
| mAvailThumbnailBitmap = null 
| mBackupAgents = [email protected] (0x2acf1e40) 
| mBoundApplication = [email protected] (0x2acd0980) 
| mCompatConfiguration = [email protected] (0x2acdb7e0) 
| mConfiguration = [email protected] (0x2acdb848) 
| mCoreSettings = [email protected] (0x2acf60d0) 
| mCurDefaultDisplayDpi = 480 
| mDensityCompatMode = false 
| mGcIdler = [email protected] (0x2aced5d0) 
| mGcIdlerScheduled = false 
| mH = [email protected] (0x2ac02080) 
| mInitialApplication = <app-package>[email protected] (0x2ac752b8) 
| mInstrumentation = [email protected] (0x2acac280) 
| mInstrumentationAppDir = null 
| mInstrumentationLibDir = null 
| mInstrumentationPackageName = null 
| mInstrumentationSplitAppDirs = null 
| mInstrumentedAppDir = null 
| mInstrumentedLibDir = null 
| mInstrumentedSplitAppDirs = null 
| mJitEnabled = true 
| mLastAssistStructures = [email protected] (0x2acf60e8) 
| mLastSessionId = 0 
| mLifecycleSeq = 3 
| mLocalProviders = [email protected] (0x2acf1e60) 
| mLocalProvidersByName = [email protected] (0x2acf1e80) 
| mLooper = [email protected] (0x2ac02060) 
| mMainThreadConfig = [email protected] (0x2acdb8b0) 
| mNewActivities = null 
| mNumVisibleActivities = 1 
| mOnPauseListeners = [email protected] (0x2acf1ea0) 
| mPackages = [email protected] (0x2acf1ec0) 
| mPendingConfiguration = null 
| mProfiler = [email protected] (0x2acf6100) 
| mProviderMap = [email protected] (0x2acf1ee0) 
| mProviderRefCountMap = [email protected] (0x2acf1f00) 
| mRelaunchingActivities = [email protected] (0x2acf6118) 
| mResourcePackages = [email protected] (0x2acf1f20) 
| mResourcesManager = [email protected] (0x2ac50160) 
| mServices = [email protected] (0x2acf1f40) 
| mSomeActivitiesChanged = true 
| mSystemContext = null 
| mSystemThread = false 
| mThumbnailCanvas = null 
| mThumbnailHeight = -1 
| mThumbnailWidth = -1 
| mUpdatingSystemConfig = false 
| shadow$_klass_ = android.app.ActivityThread 
| shadow$_monitor_ = 0 
* Instance of android.util.ArrayMap 
| static DEBUG = false 
| static BASE_SIZE = 4 
| static EMPTY = [email protected] (0x7059baf0) 
| static mBaseCache = java.lang.Object[8]@717433776 (0x2ac32bb0) 
| static mBaseCacheSize = 2 
| static $classOverhead = byte[453]@1885300129 (0x705f65a1) 
| static EMPTY_IMMUTABLE_INTS = int[0]@1884928784 (0x7059bb10) 
| static mTwiceBaseCacheSize = 0 
| static mTwiceBaseCache = null 
| static CACHE_SIZE = 10 
| static TAG = [email protected] (0x707a9928) 
| mArray = java.lang.Object[8]@718274320 (0x2acfff10) 
| mCollections = null 
| mHashes = int[4]@718411680 (0x2ad217a0) 
| mIdentityHashCode = false 
| mSize = 1 
| shadow$_klass_ = android.util.ArrayMap 
| shadow$_monitor_ = 0 
* Array of java.lang.Object[] 
| [0] = [email protected] (0x2ad05fe0) 
| [1] = <app-package>[email protected] (0x2ad0ddc0) 
| [2] = null 
| [3] = null 
| [4] = null 
| [5] = null 
| [6] = null 
| [7] = null 
* Instance of <app-package>.service.SocketService 
| static MESSAGE = [email protected] (0x70137f20) 
| static TEMP_ID = [email protected] (0x2ad21fc0) 
| static $change = null 
| static SESSION_ID = [email protected] (0x2ad2aa88) 
| static LIMIT = [email protected] (0x70137298) 
| static $classOverhead = byte[1708]@718645249 (0x2ad5a801) 
| static KEEP_ALIVE = 500 
| static USER_CONNECTED = [email protected] (0x2ad436d0) 
| static TO_USER_ID = [email protected] (0x2ad21fe0) 
| static CHAT_USER_ID = [email protected] (0x2ae8f510) 
| static ACCESS_TOKEN = [email protected]80 (0x2ac005d8) 
| static ON_SOCKET_CONNECTED = 100 
| static serialVersionUID = 0 
| static USER_ID = [email protected] (0x7078db90) 
| static USER_MESSAGE = [email protected] (0x2ae8f5b0) 
| static CHAT_MESSAGE = [email protected] (0x2ae8f4e8) 
| static FROM_MESSAGE_ID = [email protected] (0x2aea16d0) 
| static MESSAGE_TYPE = [email protected] (0x2ae8f538) 
| static USER_TYPING = [email protected] (0x2ae8f5d8) 
| static PAY_MESSAGE = [email protected] (0x2ae8f560) 
| compositeSubscription = [email protected] (0x2ad02470) 
| handler = <app-package>[email protected] (0x2ae48d40) 
| messenger = [email protected] (0x2ad02460) 
| onChatMessage = <app-package>[email protected] (0x2ad02430) 
| onPayMessage = <app-package>[email protected] (0x2ad862f8) 
| onUserConnected = <app-package>[email protected] (0x2ad02440) 
| onUserMessage = <app-package>[email protected] (0x2ad02420) 
| onUserTyping = <app-package>[email protected] (0x2ad86318) 
| ready = true 
| referenceWatcher = [email protected] (0x2ac75308) 
| sessionId = [email protected] (0x2ae20ee0) 
| slavicSocketApi = [email protected] (0x2ad02e60) 
| socket = [email protected] (0x2ae6cf70) 
| storIOSQLite = [email protected]08 (0x2ae6d328) 
| taskScheduler = <app-package>[email protected] (0x2ad02450) 
| mActivityManager = [email protected] (0x2ac01250) 
| mApplication = <app-package>[email protected] (0x2ac752b8) 
| mClassName = [email protected] (0x2ad201c8) 
| mStartCompatibility = false 
| mThread = [email protected] (0x2ac04100) 
| mToken = [email protected] (0x2ad05fe0) 
| mBase = [email protected] (0x2ae0d3c0) 
| shadow$_klass_ = <app-package>.service.SocketService 
| shadow$_monitor_ = -2028143957 
* Excluded Refs: 
| Field: android.view.Choreographer$FrameDisplayEventReceiver.mMessageQueue (always) 
| Thread:FinalizerWatchdogDaemon (always) 
| Thread:main (always) 
| Thread:LeakCanary-Heap-Dump (always) 
| Class:java.lang.ref.WeakReference (always) 
| Class:java.lang.ref.SoftReference (always) 
| Class:java.lang.ref.PhantomReference (always) 
| Class:java.lang.ref.Finalizer (always) 
| Class:java.lang.ref.FinalizerReference (always) 

Почему сервис обозначен как утечка? UPD: Я удалил явный запуск/остановку службы и задержку остановки из onUnbind, но утечка остается неизменной.

+0

для предотвращения утечек Я хотел бы предложить регистрации/ссылки на службе в методе OnCreate вашего приложения class.eg MediaUploaderService.StartService (это, MediaUploaderService.START_APP_START), то в вашей службе в onStartCommand методы убедитесь, что вы имеете возвращенное обслуживание. START_STICK, который сообщает ОС, чтобы воссоздать службу после того, как у нее достаточно памяти, и снова вызовите onStartCommand() с нулевым намерением. Это должно помочь решить проблему утечки. См. Также эту ссылку. http://stackoverflow.com/questions/9093271/start-sticky-and-start-not-sticky – Zidane

+0

@ Zidane, это не совсем то, что я искал. На данный момент я удалил явное начало/остановку и задержку остановки службы в onUnbind, так что служба будет уничтожена, если никакая активность не будет привязана к ней быстро. Но утечка остается, возможно, это необходимая утечка для связанных служб. –

ответ