例如,我有以下自定义应用程序类的代码(在项目中“激活”LeakCanary)
public class MyApp extends Application {
private RefWatcher refWatcher;
@Override
public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
refWatcher = LeakCanary.install(this);
}
public void watch(Object o) {
refWatcher.watch(o);
}
}
我有以下活动:
public class LeakActivity extends AppCompatActivity {
private String str;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_memory_leak);
str = "Pam Pam";
((MyApp)getApplication()).watch(str);
}
}
每次在配置更改(屏幕旋转)后活动开始或重新创建时,我都会看到来自 LeakCanary 的“str”泄漏通知
Could not dump heap, previous analysis still is in progress.
In com.daxh.explore.myapp:0.3:3.
* java.lang.String has leaked:
* GC ROOT static android.app.ActivityThread.sCurrentActivityThread
* references android.app.ActivityThread.mActivities
* references android.util.ArrayMap.mArray
* references array java.lang.Object[].[3]
* references android.app.ActivityThread$ActivtyClientRecord.activity
* references com.daxh.explore.myapp.activities.LeakActivity.str
* leaks java.lang.String instance
* Retaining: 38B.
* Reference Key: 9967ddcf-b2bf-4e9f-8f3e-ef007931f9b2
* Device: unknown Android Android SDK built for x86_64 sdk_google_phone_x86_64
1.5 00f37f5
* Durations: watch=5325ms, gc=110ms, heap dump=381ms, analysis=4286ms
* Details:
* Class android.app.ActivityThread
| static SERVICE_DONE_EXECUTING_STOP = 2
| static THUMBNAIL_FORMAT = android.graphics.Bitmap$Config@1887272032 (0x707d7c60)
| static MIN_TIME_BETWEEN_GCS = 5000
| static DEBUG_SERVICE = false
| static DEBUG_PROVIDER = false
| static sMainThreadHandler = android.app.ActivityThread$H@314965280 (0x12c5fd20)
| static sCurrentBroadcastIntent = java.lang.ThreadLocal@1948209872 (0x741f52d0)
| static PATTERN_SEMICOLON = java.util.regex.Pattern@1948519600 (0x74240cb0)
| static sPackageManager = android.content.pm.IPackageManager$Stub$Proxy@314982592 (0x12c640c0)
| static DEBUG_CONFIGURATION = false
| static DEBUG_BROADCAST = false
| static SERVICE_DONE_EXECUTING_START = 1
| static DEBUG_MESSAGES = false
| static DEBUG_BACKUP = false
| static TAG = java.lang.String@1879056976 (0x70002250)
| static SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003
| static HEAP_FULL_COLUMN = java.lang.String@1879025368 (0x6fffa6d8)
| static $staticOverhead = byte[208]@1888712369 (0x709376b1)
| static LOG_ON_PAUSE_CALLED = 30021
| static SERVICE_DONE_EXECUTING_ANON = 0
| static sCurrentActivityThread = android.app.ActivityThread@314790144 (0x12c35100)
| static LOG_ON_RESUME_CALLED = 30022
| static ACTIVITY_THREAD_CHECKIN_VERSION = 3
| static DEBUG_RESULTS = false
| static HEAP_COLUMN = java.lang.String@1879025344 (0x6fffa6c0)
| static localLOGV = false
| static DEBUG_MEMORY_TRIM = false
* Instance of android.app.ActivityThread
| static SERVICE_DONE_EXECUTING_STOP = 2
| static THUMBNAIL_FORMAT = android.graphics.Bitmap$Config@1887272032 (0x707d7c60)
| static MIN_TIME_BETWEEN_GCS = 5000
| static DEBUG_SERVICE = false
| static DEBUG_PROVIDER = false
| static sMainThreadHandler = android.app.ActivityThread$H@314965280 (0x12c5fd20)
| static sCurrentBroadcastIntent = java.lang.ThreadLocal@1948209872 (0x741f52d0)
| static PATTERN_SEMICOLON = java.util.regex.Pattern@1948519600 (0x74240cb0)
| static sPackageManager = android.content.pm.IPackageManager$Stub$Proxy@314982592 (0x12c640c0)
| static DEBUG_CONFIGURATION = false
| static DEBUG_BROADCAST = false
| static SERVICE_DONE_EXECUTING_START = 1
| static DEBUG_MESSAGES = false
| static DEBUG_BACKUP = false
| static TAG = java.lang.String@1879056976 (0x70002250)
| static SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003
| static HEAP_FULL_COLUMN = java.lang.String@1879025368 (0x6fffa6d8)
| static $staticOverhead = byte[208]@1888712369 (0x709376b1)
| static LOG_ON_PAUSE_CALLED = 30021
| static SERVICE_DONE_EXECUTING_ANON = 0
| static sCurrentActivityThread = android.app.ActivityThread@314790144 (0x12c35100)
| static LOG_ON_RESUME_CALLED = 30022
| static ACTIVITY_THREAD_CHECKIN_VERSION = 3
| static DEBUG_RESULTS = false
| static HEAP_COLUMN = java.lang.String@1879025344 (0x6fffa6c0)
| static localLOGV = false
| static DEBUG_MEMORY_TRIM = false
| mActivities = android.util.ArrayMap@314965312 (0x12c5fd40)
| mAllApplications = java.util.ArrayList@314965376 (0x12c5fd80)
| mAppThread = android.app.ActivityThread$ApplicationThread@314965248 (0x12c5fd00)
| mAvailThumbnailBitmap = null
| mBackupAgents = android.util.ArrayMap@314965408 (0x12c5fda0)
| mBoundApplication = android.app.ActivityThread$AppBindData@315023456 (0x12c6e060)
| mCompatConfiguration = android.content.res.Configuration@314730336 (0x12c26760)
| mConfiguration = android.content.res.Configuration@314730240 (0x12c26700)
| mCoreSettings = android.os.Bundle@314975552 (0x12c62540)
| mCurDefaultDisplayDpi = 560
| mDensityCompatMode = false
| mGcIdler = android.app.ActivityThread$GcIdler@314734688 (0x12c27860)
| mGcIdlerScheduled = false
| mH = android.app.ActivityThread$H@314965280 (0x12c5fd20)
| mInitialApplication = com.daxh.explore.myapp.MyAppApp@315135744 (0x12c89700)
| mInstrumentation = android.app.Instrumentation@314896144 (0x12c4ef10)
| mInstrumentationAppDir = null
| mInstrumentationLibDir = null
| mInstrumentationPackageName = null
| mInstrumentationSplitAppDirs = null
| mInstrumentedAppDir = null
| mInstrumentedLibDir = null
| mInstrumentedSplitAppDirs = null
| mJitEnabled = true
| mLocalProviders = android.util.ArrayMap@314965600 (0x12c5fe60)
| mLocalProvidersByName = android.util.ArrayMap@314965632 (0x12c5fe80)
| mLooper = android.os.Looper@314965184 (0x12c5fcc0)
| mMainThreadConfig = android.content.res.Configuration@314730048 (0x12c26640)
| mNewActivities = null
| mNumVisibleActivities = 1
| mOnPauseListeners = android.util.ArrayMap@314965664 (0x12c5fea0)
| mPackages = android.util.ArrayMap@314965440 (0x12c5fdc0)
| mPendingConfiguration = null
| mProfiler = android.app.ActivityThread$Profiler@315122720 (0x12c86420)
| mProviderMap = android.util.ArrayMap@314965536 (0x12c5fe20)
| mProviderRefCountMap = android.util.ArrayMap@314965568 (0x12c5fe40)
| mRelaunchingActivities = java.util.ArrayList@314965504 (0x12c5fe00)
| mResourcePackages = android.util.ArrayMap@314965472 (0x12c5fde0)
| mResourcesManager = android.app.ResourcesManager@314965696 (0x12c5fec0)
| mServices = android.util.ArrayMap@314965344 (0x12c5fd60)
| mSomeActivitiesChanged = true
| mSystemContext = android.app.ContextImpl@315125888 (0x12c87080)
| mSystemThread = false
| mThumbnailCanvas = null
| mThumbnailHeight = -1
| mThumbnailWidth = -1
* Instance of android.util.ArrayMap
| static EMPTY = android.util.ArrayMap@1887219864 (0x707cb098)
| static BASE_SIZE = 4
| static DEBUG = false
| static EMPTY_IMMUTABLE_INTS = int[0]@1887206984 (0x707c7e48)
| static mBaseCacheSize = 0
| static CACHE_SIZE = 10
| static mBaseCache = null
| static mTwiceBaseCacheSize = 1
| static mTwiceBaseCache = java.lang.Object[16]@316499536 (0x12dd6650)
| static $staticOverhead = byte[80]@1888643129 (0x70926839)
| static TAG = java.lang.String@1879059712 (0x70002d00)
| mArray = java.lang.Object[8]@315835968 (0x12d34640)
| mCollections = null
| mHashes = int[4]@315628768 (0x12d01ce0)
| mSize = 2
* Array of java.lang.Object[]
| [0] = android.os.BinderProxy@315011488 (0x12c6b1a0)
| [1] = android.app.ActivityThread$ActivityClientRecord@314589568 (0x12c04180)
| [2] = android.os.BinderProxy@317075616 (0x12e630a0)
| [3] = android.app.ActivityThread$ActivityClientRecord@317288320 (0x12e96f80)
| [4] = null
| [5] = null
| [6] = null
| [7] = null
* Instance of android.app.ActivityThread$ActivityClientRecord
| activity = com.daxh.explore.myapp.activities.LeakActivity@315971680 (0x12d55860)
| activityInfo = android.content.pm.ActivityInfo@317288192 (0x12e96f00)
| compatInfo = android.content.res.CompatibilityInfo@317076768 (0x12e63520)
| createdConfig = null
| embeddedID = null
| hideForNow = false
| ident = 958616894
| intent = android.content.Intent@316506176 (0x12dd8040)
| isForward = true
| lastNonConfigurationInstances = null
| mPendingRemoveWindow = null
| mPendingRemoveWindowManager = null
| newConfig = null
| nextIdle = null
| onlyLocalRequest = false
| packageInfo = android.app.LoadedApk@314593792 (0x12c05200)
| parent = null
| paused = false
| pendingConfigChanges = 0
| pendingIntents = null
| pendingResults = null
| persistentState = null
| profilerInfo = null
| referrer = java.lang.String@317076800 (0x12e63540)
| startsNotResumed = false
| state = null
| stopped = false
| token = android.os.BinderProxy@317075616 (0x12e630a0)
| voiceInteractor = null
| window = com.android.internal.policy.impl.PhoneWindow@315859200 (0x12d3a100)
* Instance of com.daxh.explore.myapp.activities.LeakActivity
| str = java.lang.String@316651872 (0x12dfb960)
| mDelegate = android.support.v7.app.AppCompatDelegateImplV14@314801856 (0x12c37ec0)
| mEatKeyUpEvent = false
| mResources = null
| mThemeId = 2131230884
| mCreated = true
| mFragments = android.support.v4.app.FragmentController@316866960 (0x12e30190)
| mHandler = android.support.v4.app.FragmentActivity$1@317088416 (0x12e662a0)
| mNextCandidateRequestIndex = 0
| mOptionsMenuInvalidated = false
| mPendingFragmentActivityResults = android.support.v4.util.SparseArrayCompat@317092160 (0x12e67140)
| mReallyStopped = false
| mRequestedPermissionsFromFragment = false
| mResumed = false
| mRetaining = false
| mStopped = false
| mStartedActivityFromFragment = false
| mStartedIntentSenderFromFragment = false
| mExtraDataMap = android.support.v4.util.SimpleArrayMap@317088256 (0x12e66200)
| mActionBar = null
| mActivityInfo = android.content.pm.ActivityInfo@317288192 (0x12e96f00)
| mActivityTransitionState = android.app.ActivityTransitionState@316491264 (0x12dd4600)
| mAllLoaderManagers = android.util.ArrayMap@317305344 (0x12e9b200)
| mApplication = com.daxh.explore.myapp.MyAppApp@315135744 (0x12c89700)
| mCalled = true
| mChangeCanvasToTranslucent = false
| mChangingConfigurations = false
| mCheckedForLoaderManager = true
| mComponent = android.content.ComponentName@316883056 (0x12e34070)
| mConfigChangeFlags = 0
| mContainer = android.app.Activity$1@316866912 (0x12e30160)
| mCurrentConfig = android.content.res.Configuration@316862816 (0x12e2f160)
| mDecor = com.android.internal.policy.impl.PhoneWindow$DecorView@316164096 (0x12d84800)
| mDefaultKeyMode = 0
| mDefaultKeySsb = null
| mDestroyed = false
| mDoReportFullyDrawn = true
| mEmbeddedID = null
| mEnableDefaultActionBarUp = false
| mEnterTransitionListener = android.app.SharedElementCallback$1@1887233040 (0x707ce410)
| mExitTransitionListener = android.app.SharedElementCallback$1@1887233040 (0x707ce410)
| mFinished = false
| mFragments = android.app.FragmentManagerImpl@314915296 (0x12c539e0)
| mHandler = android.os.Handler@317088224 (0x12e661e0)
| mIdent = 958616894
| mInstanceTracker = android.os.StrictMode$InstanceTracker@316866928 (0x12e30170)
| mInstrumentation = android.app.Instrumentation@314896144 (0x12c4ef10)
| mIntent = android.content.Intent@316506176 (0x12dd8040)
| mLastNonConfigurationInstances = null
| mLoaderManager = null
| mLoadersStarted = true
| mMainThread = android.app.ActivityThread@314790144 (0x12c35100)
| mManagedCursors = java.util.ArrayList@317088096 (0x12e66160)
| mManagedDialogs = null
| mMenuInflater = null
| mParent = null
| mReferrer = java.lang.String@317076800 (0x12e63540)
| mResultCode = 0
| mResultData = null
| mResumed = true
| mSearchManager = null
| mStartedActivity = false
| mStopped = false
| mTemporaryPause = false
| mTitle = java.lang.String@316515168 (0x12dda360)
| mTitleColor = 0
| mTitleReady = true
| mToken = android.os.BinderProxy@317075616 (0x12e630a0)
| mTranslucentCallback = null
| mUiThread = java.lang.Thread@1948209064 (0x741f4fa8)
| mVisibleBehind = false
| mVisibleFromClient = true
| mVisibleFromServer = true
| mVoiceInteractor = null
| mWindow = com.android.internal.policy.impl.PhoneWindow@315859200 (0x12d3a100)
| mWindowAdded = true
| mWindowManager = android.view.WindowManagerImpl@317089024 (0x12e66500)
| mInflater = com.android.internal.policy.impl.PhoneLayoutInflater@317399872 (0x12eb2340)
| mOverrideConfiguration = null
| mResources = android.content.res.Resources@314730720 (0x12c268e0)
| mTheme = android.content.res.Resources$Theme@317089088 (0x12e66540)
| mThemeResource = 2131230884
| mBase = android.app.ContextImpl@314923264 (0x12c55900)
* Instance of java.lang.String
| static REPLACEMENT_CHAR = �
| static serialVersionUID = -6849794470754667710
| static ASCII = char[128]@1887135184 (0x707b65d0)
| static $staticOverhead = byte[32]@1887282065 (0x707da391)
| static CASE_INSENSITIVE_ORDER = java.lang.String$CaseInsensitiveComparator@1887134984 (0x707b6508)
| count = 7
| hashCode = 864575192
| offset = 0
| value = char[7]@316651840 (0x12dfb940)
* Excluded Refs:
| Field: android.view.inputmethod.InputMethodManager.mNextServedView
| Field: android.view.inputmethod.InputMethodManager.mServedView
| Field: android.view.inputmethod.InputMethodManager.mServedInputConnection
| Field: android.view.inputmethod.InputMethodManager.mCurRootView
| Field: android.animation.LayoutTransition$1.val$parent
| Field: android.view.textservice.SpellCheckerSession$1.this$0
| Field: android.support.v7.internal.widget.ActivityChooserModel.mActivityChoserModelPolicy
| Field: android.widget.ActivityChooserModel.mActivityChoserModelPolicy
| Field: android.accounts.AccountManager$AmsTask$Response.this$1
| Field: android.media.MediaScannerConnection.mContext
| Field: android.os.UserManager.mContext
| Field: android.media.AudioManager$1.this$0
| Field: android.widget.Editor$Blink.this$0
| Field: android.net.ConnectivityManager.sInstance
| Field: android.view.Choreographer$FrameDisplayEventReceiver.mMessageQueue (always)
| Static field: android.text.TextLine.sCached
| 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)
任何想法或解释为什么会发生这种情况?