Leakcanary memory leak monitoring Performance optimization Introduction principle

Source: Internet
Author: User

Leakcanary memory leak monitoring Performance optimization Introduction principle
Github:https://github.com/square/leakcanary
Demo Address: Https://github.com/baiqiantao/LeakCanaryTest.git

Directory

Directory
Simple to use
More about
Custom Leakcanary
Test case
Application
Mainactivity
Memory leaks caused by static members
Single-Instance memory leak

Simple to use

A memory leak detection 内存泄露检测 Library for Android and Java.

A small leak would sink a great ship. --Benjamin Franklin
Dikes, destroyed in the nest. --"Han Fei zi and Shang"

Add Dependencies:

dependencies {  debugImplementation ‘com.squareup.leakcanary:leakcanary-android:1.6.1‘  debugImplementation ‘com.squareup.leakcanary:leakcanary-support-fragment:1.6.1‘ //当使用support库时添加  releaseImplementation ‘com.squareup.leakcanary:leakcanary-android-no-op:1.6.1‘ //发布时用的是无任何操作的版本}

Initialization

LeakCanary.install(application);

Once configured, in the debug build version, activity 或 fragment a notification is automatically displayed if a memory leak is detected LeakCanary .

More about
  • Why use leakcanary

    • memory leak is a programming error [programming error] , which causes the application to retain references to objects that are no longer needed 。 As a result, the memory allocated [allocated] for the object cannot be reclaimed, resulting in outofmemoryerror crash.
    • For example, an Android Activity instance is no longer needed after calling the OnDestroy method, but if a strong reference to the activity is stored in a static field, it will be prevented from being a GC [garbage collected] . The
    • leakcanary uniquely identifies an object that is longer needed, and finds a chain of references that prevent it from being garbage collected.
    • when the author first enabled Leakcanary in an app in square, he found and fixed multiple memory leaks and lowered the outofmemoryerror crash rate by 94%.
  • How does leakcanary work?

    • By RefWatcher.watch() creating a to the KeyedWeakReference watched object.
    • The background thread then checks to see if the reference is cleared, if not triggers a GC .
    • If the reference is still not cleared, dumps the heap into a. hprof file in the file system.
    • Start in a separate process HeapAnalyzerService and HeapAnalyzer use HAHA to parse the heap dump.
    • Thanks to the unique reference key , HeapAnalyzer found in the heap dump KeyedWeakReference and positioned leaking reference.
    • HeapAnalyzerGC rootsthe shortest strong reference path to the calculation and determine if there is a leak. Creates a chain of references that leads to disclosure, if any.
    • The results of the calculation are passed to the APP process and are displayed in the DisplayLeakService form of notifications.
  • How to fix a memory leak

    To fix a memory leak, you need to look at the chain and look for the reference that caused the leak, that is, which reference should have been cleared when the leak occurred. Leakcanary a red underline to highlight a reference that could cause a leak.

  • How to copy leak trace information

    Can be copied via Logcat or via the Leaks App's menu ·

  • Can the Android SDK cause a leak?

    Is. There are already many known memory leaks in the AOSP and in the manufacturer implementations. When such a leak occurs, you can hardly resolve the issue as an application developer.
    For this reason, Leakcanary has a built-in list of known Android vulnerabilities that can be ignored: Androidexcludedrefs.java.

  • How to mine leak information through leak trace

    Sometimes leak trace is not enough, you need to use MAT or yourkit to dig the heap dump. Here's how to find a leak instance in a heap dump:

    • Find com.squareup.leakcanary.KeyedWeakReference all instances of
    • For each of these, see the key fields.
    • Locate the key field equal to the Leakcanary report of the reference key KeyedWeakReference .
    • The Keyedweakreference referent field that you found is the object of your memory leak.
    • After that, the problem is in your hands. A good start is to view GC Roots的最短路径 (except for weak references).
  • How to fix build errors

    • If Leakcan-android is not in the external libraries list in Android studio, but Leakcanary-analyzer and Leakcanary-watcher are there: try to do a Clean Build. If the problem persists, try building it from the command line.
    • Error:package Com.squareup.leakcanary does not exist: If you have additional build types instead of debug and release, you will also need to add specific dependencies for these build types (xxxcompi Le).
  • Leakcanary How many methods are added

    • If you use ProGuard , the answer is 9 or 0.
    • Leakcanary should only be used in debug builds and must be disabled in the release version. We have provided a special null dependency for your release version: leakcanary-android-no-op .
    • The full version of Leakcanary is larger and should never be published in your release release.
  • Who's pushing leakcanary?

    Leakcanary is created and open source by @pyricau and is currently maintained by @jrodbx, @JakeWharton and @pyricau.

  • Why is it called leakcanary?

    Leakcanary This name is the reference to the canary in the coal mine [canary in a coal mine] , because Leakcanary is a sentinel used to detect risks by early warning hazards [advance warning of a danger] [detect risks] [sentinel] .

  • Instant run may trigger an invalid leaks

    Enabling the instant run feature of Android Studio may cause Leakcanary to report an invalid memory leak. See the problem #37967114 (https://issuetracker.google.com/issues/37967114) on the Android Issue Tracker.

  • I know I have leaks, why does the notification not show

    Do you attached to a debugger? The leakcanary ignores leak detection when debugging to avoid false positives.

Custom Leakcanary

    • How to observe objects that have a life cycle

      In your application, you may have other objects that have life cycles, such as fragment,service,dagger components. You can use Refwatcher to monitor instances where garbage collection should take place: Refwatcher.watch (schrodingercat);

    • Use no-op dependency

      Release version of Leakcanary-android-no-op dependency contains only leakcanary and Refwatcher classes. If you want to customize Leakcanary, you need to make sure that the customizations only appear in the debug version, because it may reference classes that do not exist in the leakcanary-android-no-op dependency.

    • Custom icons and labels

      displayleakactivity comes with a default icon and label that you can Change it by providing R.mipmap.leak_canary_icon and R.string.leak_canary_display_activity_label in:

    • The default logic for the Install method

public static RefWatcher install(Application application) {   return refWatcher(application)      .listenerServiceClass(DisplayLeakService.class)      .excludedRefs(AndroidExcludedRefs.createAppDefaults().build())      .buildAndInstall();}
    • No monitoring of specific activity
      By default, leakcanary monitors all activity. You can customize installation steps to perform different actions, such as ignoring leaks for a type of activity:
RefWatcher refWatcher = LeakCanary.refWatcher(this)      .watchActivities(false)      .buildAndInstall();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {   @Override   public void onActivityDestroyed(Activity activity) {      if (activity instanceof IgnoreActivity) {         return;      }      refWatcher.watch(activity);   }   //...});
    • Turn leakcanary on and off at run time
refWatcher = LeakCanary.refWatcher(this)      .heapDumper(getHeapDumper()) //在运行时开启和关闭LeakCanary      .buildAndInstall();
public TogglableHeapDumper getHeapDumper() { if (heapDumper == null) {  LeakDirectoryProvider leakDirectoryProvider = LeakCanaryInternals.getLeakDirectoryProvider(this);  AndroidHeapDumper defaultDumper = new AndroidHeapDumper(this, leakDirectoryProvider);  heapDumper = new TogglableHeapDumper(defaultDumper); } return heapDumper;}
public class TogglableHeapDumper implements HeapDumper { private final HeapDumper defaultDumper; private boolean enabled = true; public TogglableHeapDumper(HeapDumper defaultDumper) {  this.defaultDumper = defaultDumper; } public void setEnabled(boolean enabled) {  this.enabled = enabled; } @Override public File dumpHeap() {  return enabled ? defaultDumper.dumpHeap() : HeapDumper.RETRY_LATER; }}
MyApplication.app().getHeapDumper().setEnabled(false);
Test Case Application
public class MyApplication extends application {private refwatcher refwatcher; private static MyApplication app; private Togglableheapdumper Heapdumper;  @Override public void OnCreate () {super.oncreate (); if (leakcanary.isinanalyzerprocess (this)) {log.i ("BQT", "the process is dedicated to leakcanary for heap analysis.") You should not initialize your app in this process.   ");  Return } Refwatcher = Leakcanary.refwatcher (this). Watchactivities (TRUE)//default is true to monitor all activity, You can set it to false and then specify the activity that you want to monitor. Watchfragments (TRUE)///default is true to monitor native Fragment, if a support dependency is added, The fragment in support is also monitored. Watchdelay (1, timeunit.seconds)//Set How long it should wait until it checks whether the tracking object has been garbage collected. Maxstoredheapdumps (7)//Set L Eakcanary the maximum number of heap dumps that can be saved, the default is 7. Excludedrefs (Getexcludedrefs ())//Ignore specific references, this junk is always set to not take effect. Heapdumper (Getheapdum Per ())//Open and close Leakcanary//.listenerserviceclass at runtime ()//You can change the default behavior to upload leak trace and heap dump to the server you select: Buildandinst  All (); App = this; } private Excludedrefs Getexcludedrefs () {return androidexcludedrefs.createappdefaults ()//after a large numberTest, I feel that TMD completely ignores the memory leaks in activity and fragment. Instancefield ("Com.bqt.test.Single", "ImageView")//class name, field name. Staticfield (" Com.bqt.test.StaticLeakActivity "," bitmap ")//class name, static field name. Clazz (" com.bqt.test.StaticLeakActivity ")// Ignores all fields and static fields for all subclasses of the provided class name. Thread ("Thread-10086")//ignores the specified thread, the general main thread is named "main" and the child thread is named "thread-integer". build ();  Ignored references if manually monitored by watch, their memory leaks are still monitored} public static MyApplication app () {return app;} public Refwatcher Getrefwatcher () {return refwatcher;} public Togglableheapdumper Getheapdumper () {if (Heapdumper = = null) {Leakdirectoryprovider L   Eakdirectoryprovider = Leakcanaryinternals.getleakdirectoryprovider (this);   Androidheapdumper defaultdumper = new Androidheapdumper (this, leakdirectoryprovider);  Heapdumper = new Togglableheapdumper (defaultdumper); } return heapdumper; }}
Mainactivity
public class Mainactivity extends Fragmentactivity implements Adapterview.onitemclicklistener {private framelayout Framelayout;  @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);  ListView ListView = New ListView (this);  String[] Array = {"Static member-caused memory leak", "single case-caused memory leak: Fragment", "Disable Leakcanary", "", "}; Listview.setadapter (New arrayadapter<> (this, Android.  R.layout.simple_list_item_1, Arrays.aslist (array));  Listview.setonitemclicklistener (this);  Framelayout = new Framelayout (this);  Framelayout.setid (r.id.fragment_id);  Listview.addfooterview (framelayout); Setcontentview (ListView);   } @Override public void Onitemclick (adapterview<?> parent, view view, int position, long ID) {switch (position) {    Case 0:startactivity (New Intent (this, staticleakactivity.class));   Break Case 1:getsupportfragmentmanager (). BeginTransaction (). Add (Framelayout.getid (), New Singleleakfragment (), "single      Leakfragment "). commit ();   Break    Case 2:myapplication.app (). Getheapdumper (). setenabled (false);   Break  Default:break; } }}
Memory leaks caused by static members
public class StaticLeakActivity extends Activity { private static Bitmap bitmap; @Override protected void onCreate(@Nullable Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  ImageView imageView = new ImageView(this);  bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);  imageView.setImageBitmap(bitmap);  setContentView(imageView); }}


Related information:

* com.bqt.test.StaticLeakActivity has leaked:* InputMethodManager$ControlledInputConnectionWrapper.!(mParentInputMethodManager)!* ? InputMethodManager.!(mLastSrvView)!* ? PhoneWindow$DecorView.mContext* ? StaticLeakActivity* Reference Key: 7f96d2f1-bf17-47e2-84ad-cd5976d72766* Device: HUAWEI HONOR PLK-UL00 PLK-UL00* Android Version: 6.0 API: 23 LeakCanary: 1.6.1 26145bf* Durations: watch=1007ms, gc=149ms, heap dump=1840ms, analysis=6567ms
Single-Instance memory leak
public class SingleLeakFragment extends Fragment { private ImageView imageView; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  imageView = new ImageView(getContext());  return imageView; } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {  super.onViewCreated(view, savedInstanceState);  imageView.setImageResource(R.drawable.icon);  Single.SINGLETON.setImageView(imageView);//单例中引用View同样会导致Activity内存泄漏 }}
public enum Single { @SuppressLint("StaticFieldLeak") SINGLETON; //定义一个枚举的元素,它就代表了Single的一个实例 private ImageView imageView; public void setImageView(ImageView imageView) {  this.imageView = imageView; }}


Related information:

* com.bqt.test.SingleLeakFragment has leaked:* InputMethodManager$ControlledInputConnectionWrapper.!(mParentInputMethodManager)!* ? InputMethodManager.!(mLastSrvView)!* ? ListView.mOnItemClickListener* ? MainActivity.mFragments* ? FragmentController.mHost* ? FragmentActivity$HostCallbacks.mFragmentManager* ? FragmentManagerImpl.mAdded* ? ArrayList.array* ? array Object[].[0]* ? SingleLeakFragment* Reference Key: 4877bf10-596c-440f-b69c-5d239f670944* Device: HUAWEI HONOR PLK-UL00 PLK-UL00* Android Version: 6.0 API: 23 LeakCanary: 1.6.1 26145bf* Durations: watch=17245ms, gc=138ms, heap dump=1675ms, analysis=8159ms

2018-10-2

Leakcanary memory leak monitoring Performance optimization Introduction principle

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.