范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

阿里一面之LeakCanary内存泄漏监测原理总结

  本文通过在阿里面试遇到的问题总结而出,如有不对地方,请及时批评指正。篇幅较长,请耐心阅读。简介:
  LeakCanary是一个开源的内存泄漏检查工具,使用简单,主要用来监测Activity和Fragment是否发生内存泄漏。如果发生内存泄漏,直接以引用链的形式展示出造成内存泄漏对象。使用步骤添加build.gradle依懒。  debugImplementation "com.squareup.leakcanary:leakcanary-android:1.6.3"   releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:1.6.3"   debugImplementation "com.squareup.leakcanary:leakcanary-support-fragment:1.6.3"
  2.在Application中初始化LeakCanary。class CustomApplication:MainApplication() {     override fun onCreate() {         super.onCreate()        if (! LeakCanary.isInAnalyzerProcess(this)) {             LeakCanary.install(this);         }     } }
  完成以上两步操作之后,当打开app运行时,如果Activity或Fragment发生内存泄漏,会以通知的形式提醒用户。源码分析
  先通过流程图来看一下LeakCanary工作原理,如图所示:
  LeakCanary初始化
  1.在application中注册。class CustomApplication:MainApplication() {     override fun onCreate() {         super.onCreate()        if (! LeakCanary.isInAnalyzerProcess(this)) {            //注册leakcanary             LeakCanary.install(this);         }     } }
  2.构建观察者RefWatcher。public static RefWatcher install(Application application) {     //构建观察者RefWatcher     return refWatcher(application).listenerServiceClass(DisplayLeakService.class)         .excludedRefs(AndroidExcludedRefs.createAppDefaults().build())         .buildAndInstall(); }
  3.构建不同的观察者ActivityRefWatcher或FragmentRefWatcher。public RefWatcher buildAndInstall() {     if (LeakCanaryInternals.installedRefWatcher != null) {       throw new UnsupportedOperationException("buildAndInstall() should only be called once.");   }     RefWatcher refWatcher = build();     if (refWatcher != DISABLED) {         //观察activity       if (watchActivities) {         ActivityRefWatcher.install(context, refWatcher);     }       //观察fragment       if (watchFragments) {         FragmentRefWatcher.Helper.install(context, refWatcher);     }   }     LeakCanaryInternals.installedRefWatcher = refWatcher;     return refWatcher; }
  4.监测activity生命周期。public static void install(Context context, RefWatcher refWatcher) {     Application application = (Application) context.getApplicationContext();     ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);    //注册生命周期     application.registerActivityLifecycleCallbacks(activityRefWatcher.lifecycleCallbacks); }
  5.将观察对象activity添加到被观察者队列。private final Application.ActivityLifecycleCallbacks lifecycleCallbacks =     new ActivityLifecycleCallbacksAdapter() {         @Override public void onActivityDestroyed(Activity activity) {             //在activity的onDestroy生命周期中添加观察对象           refWatcher.watch(activity);       }     };泄漏检测
  1.将被观察对象包装成弱引用。public void watch(Object watchedReference, String referenceName) {     if (this == DISABLED) {       return;   }      //判空检查     checkNotNull(watchedReference, "watchedReference");     checkNotNull(referenceName, "referenceName");     final long watchStartNanoTime = System.nanoTime();     //生成唯一key     String key = UUID.randomUUID().toString();     //保存key     retainedKeys.add(key);     //包装成弱引用对象     final KeyedWeakReference reference =     new KeyedWeakReference(watchedReference, key, referenceName, queue);     //检查被观察对象是否被回收     ensureGoneAsync(watchStartNanoTime, reference); }
  2.检测弱引用对象是否被回收。@SuppressWarnings("ReferenceEquality") // Explicitly checking for named null. Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) {     long gcStartNanoTime = System.nanoTime();     long watchDurationMs = NANOSECONDS.toMillis(gcStartNanoTime - watchStartNanoTime);     //移除被回收对象的key     removeWeaklyReachableReferences();      if (debuggerControl.isDebuggerAttached()) {       // The debugger can create false leaks.       return RETRY;   }     //判断弱引用是否被回收     if (gone(reference)) {       return DONE;   }     //触发系统GC进行垃圾回收     gcTrigger.runGc();     //再次移除被回收对象的key     removeWeaklyReachableReferences();     //判断弱引用对象是否被回收     if (!gone(reference)) {         //将没有被回收对象的内存快照保存成文件       long startDumpHeap = System.nanoTime();       long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);        File heapDumpFile = heapDumper.dumpHeap();       if (heapDumpFile == RETRY_LATER) {         // Could not dump the heap.         return RETRY;     }       long heapDumpDurationMs = NANOSECONDS.toMillis(System.nanoTime() - startDumpHeap);       //构建内存快照文件       HeapDump heapDump = heapDumpBuilder.heapDumpFile(heapDumpFile).referenceKey(reference.key)           .referenceName(reference.name)           .watchDurationMs(watchDurationMs)           .gcDurationMs(gcDurationMs)           .heapDumpDurationMs(heapDumpDurationMs)           .build();       //将内存信息回调出去       heapdumpListener.analyze(heapDump);   }     return DONE; }内存分析
  1.启动HeapAnalyzerService进行内存分析@Override public void analyze(HeapDump heapDump) {     checkNotNull(heapDump, "heapDump");     HeapAnalyzerService.runAnalysis(context, heapDump, listenerServiceClass); }
  2.保存文件,并发送通知给用户@Override protected final void onHeapAnalyzed(HeapDump heapDump, AnalysisResult result) {     String leakInfo = leakInfo(this, heapDump, result, true);     CanaryLog.d("%s", leakInfo);      boolean resultSaved = false;     boolean shouldSaveResult = result.leakFound || result.failure != null;     if (shouldSaveResult) {      //保存内存文件       heapDump = renameHeapdump(heapDump);       resultSaved = saveResult(heapDump, result);   }      PendingIntent pendingIntent;     String contentTitle;     String contentText;     //解析内存文件     if (!shouldSaveResult) {       contentTitle = getString(R.string.leak_canary_no_leak_title);       contentText = getString(R.string.leak_canary_no_leak_text);       pendingIntent = null;   } else if (resultSaved) {       pendingIntent = DisplayLeakActivity.createPendingIntent(this, heapDump.referenceKey);        if (result.failure == null) {         if (result.retainedHeapSize == AnalysisResult.RETAINED_HEAP_SKIPPED) {           String className = classSimpleName(result.className);           if (result.excludedLeak) {             contentTitle = getString(R.string.leak_canary_leak_excluded, className);         } else {             contentTitle = getString(R.string.leak_canary_class_has_leaked, className);         }       } else {           String size = formatShortFileSize(this, result.retainedHeapSize);           String className = classSimpleName(result.className);           if (result.excludedLeak) {             contentTitle = getString(R.string.leak_canary_leak_excluded_retaining, className, size);         } else {             contentTitle =             getString(R.string.leak_canary_class_has_leaked_retaining, className, size);         }       }     } else {         contentTitle = getString(R.string.leak_canary_analysis_failed);     }       contentText = getString(R.string.leak_canary_notification_message);   } else {       contentTitle = getString(R.string.leak_canary_could_not_save_title);       contentText = getString(R.string.leak_canary_could_not_save_text);       pendingIntent = null;   }     // 每次发送一个新通知提醒用户。     int notificationId = (int) (SystemClock.uptimeMillis() / 1000);     showNotification(this, contentTitle, contentText, pendingIntent, notificationId);     afterDefaultHandling(heapDump, result, leakInfo); }
  整个监测过程主要作用如下:
  1.注册监听activity生命周期。
  2.在activity被销毁时加入弱引用队列。
  3.第一次移除不可达对象,移除ReferenceQueue中的KeyedWeakReference。
  4.主动触发GC进行垃圾回收。
  5.第二次移除不可达对象,移除ReferenceQueue中的KeyedWeakReference。
  6.判断当前是否还有对象存活,如果有保存存活对象的内存快照heapDumpFile,然后进行内存分析。
  7.启动HeapAnalyzerService对内存快照进行分析,找出GCroots引用链。
  8.发送通知给用户。
  以上就是阿里面试后总结的几个要点,还不会的同学赶紧学起来吧,感谢您的阅读,创造不易,如果您觉得本篇文章对您有帮助,请点击关注小编,您的支持就是小编创作的最大动力!

超模VirginiaGallardo身穿超短比基尼大秀身材弗吉尼亚盖拉多(VirginiaGallardo)1987年9月25日出生,是一名阿根廷模特职业舞者和演员。作为迷你泳衣的爱好者,近日弗吉尼亚盖拉多在社交平台上晒出了多张一款引领潮SteamDeck风格全新Steam大屏幕模式更新现已上线经过四个月的公开Beta测试,Valve此前承诺许就的全新Steam大屏幕模式现已面向所有用户推出。新的模式为已经有些过时的UI提供了SteamDeck风格的改造。Steam大屏幕游戏直播电脑配置详解(2023年游戏直播电脑配置推荐)很多人对于游戏直播这块,可能会觉得比较偏专业领域,需要很强大的电脑硬件,必须投入很多资源等等。今天装机天下就来和大家聊聊关于游戏直播电脑配置及其它相关问题对硬件有些概念的人,还会知7个Windows电脑自带的小功能,却干掉了很多付费软件我们拿到电脑后,都会安装各种软件,却忽略了系统自带的功能,其实也非常实用。下面这7个Windows电脑自带的小功能,却干掉了很多付费软件。01。桌面分屏功能Win10系统自带的分屏秒杀系统上云,从1342ms提升到138ms小伙伴们好呀,拖拖拉拉的我,终于把秒杀项目部署到云端上去了!这次过程也比较顺利,搭建下RabbitMQ就好了。helminstallrabbitmqbitnamirabbitmqn电脑手机互传文件开源工具汇总软件分享目录1。LANDrop2。百灵快传3。anydesk4。互传5。airdroid6。Snapdrop7。Xender8。SendAnywhere9。AirMoreLANDr今春流行的鞋子,这4双最好看!百搭又时髦!嗨,各位小仙女们,大家好呀!到了春季,除了要给自己买一些新衣服之外,鞋子也是不能缺少了,那么在今年春天有哪些流行的鞋子款式呢?如果你正打算为自己挑选一双鞋子,那么下面这4双真的不要初春别再一身黑,这3种颜色正流行,显白又气质!季节的转换,使很多人都没有了搭配方向,秋冬季节流行深色系穿搭,特别是黑色,但是到了百花盛开的春季还是要多穿点亮色系的单品呀。以下这几种流行色不可错过,第一种色彩比较实用百搭,最后一2023,大展红兔!2023春夏流行色衣橱复古红秀场中的红将律动的生命色彩融美于衣时髦精们快快获取专属于你的红色衣橱一起穿红装迎好运2023,做最红的自己色彩释义盖娅传说红色作为中国人最喜欢的颜色最有代表性的中国色,在历史发展的五款在黑色星期五最值得入手的运动鞋耐克乔丹和锐步在2022年黑色星期五发布了最好的运动鞋。随着假期的临近,发布了篮球鞋和跑步鞋指南。以下是值得入手的五款最佳运动鞋。NikeDunkLowArizonaState描述Missha谜尚爆款单品红气垫亮相李佳琦直播间斩获天猫类目榜单TOP11月28日,知名韩妆品牌Missha谜尚亮相李佳琦直播间,爆款产品红气垫一上架即被热抢,产品超高性价比及优秀妆效也让李佳琦给出了补妆等于补防晒,底妆又透又亮,遮瑕力56颗星的高分评
人间值得未来岁月漫长,依旧值得期待人间值得这一场疫情不知道大家活明白了没有?如果你还有很多心结,不妨去读一读中村恒子奥田弘美所著写的人间值得。人如何度过一生,才不会辜负生命?面对人生的终极问题,当了70年心理医生的这里有一份2022瓦屋山年度记忆,请查收一晃就到了年底因为种种原因很多小伙伴们可能错过了很多美景今天瓦妹儿就和你们一起回顾一下瓦屋山的十二个月吧!一hr月我们在雪地里共赏青羌舞蹈与小伙伴们在雪中篝火共欢迎接2022的到来广东队一战打出两名国手,后场双子星打动乔帅,一老一少仍有机会广东队以10291力克天津队,迎来了13连胜,第二阶段以来未尝败绩,一路顺风顺水,本场比赛,内线核心易建联轮休,张明池首发登场,与汉密尔顿继续组成双塔阵容,开局士气如虹,一度打出了官宣!2023年NBA第一笔交易!这是安东尼最后的机会了北京时间1月6日,马刺官方宣布,球队送出一个受保护的二轮选秀权,从凯尔特人交易得到诺阿冯莱和部分现金,马刺随即裁掉冯莱。这笔交易完成后,马刺和绿军各腾出一个球队名额,绿军省了奢侈税事关民生住房2023年这些部委工作部署将影响你我生活日前,国家发改委民政部财政部等部委陆续召开工作会议,有关部门负责人也提出了2023年工作部署,涉及民生住房财政等多领域。哪些与你我生活息息相关?一文了解增进民生福祉促进共同富裕党的三星宣布300多家公司将采用SmartThings技术IT之家1月6日消息,三星正押注其创造互联体验和为互联世界带来从容的新战略,以实现无缝的智能家居连接。三星CES2023上概述了愿景,其计划中的关键要素是将SmartThings技公司上市前离职,进入大厂转型产品经理,毕业8年我为何这么折腾Hi大家好,我是可米同学,是善知岛英语的创建者之一。碰拳个人选择之路进入互联网教育公司,深度参与付费用户100万的核心课程项目公司规模达到3000人,即将赴美上市我却选择离开,前往荷兰氢燃料电池拖拉机公司破产后重新被投资H2Trac的传奇故事仍在继续,该公司在软件公司Quantillion创始人领导的新一批投资者的带领下,再次从废墟中崛起。希尔布兰德奎恩(HilbrandKuiken)是Quant揭秘大贪官和珅发家史,深得乾隆恩宠,生财有道九岁时,他的父母去世了。当他年轻的时候,他尝到了世界上寒冷和温暖的感情。被欺负的人仍然强颜欢笑,妥协,和珅立志出人头地。他充满经验,仍屡试不中,决定另辟蹊径,放弃通过科举考试入宫,清朝身份最低的皇后,葬礼寒酸成也乾隆,败也乾隆1797年,38岁的孝淑皇后去世。丧钟敲响,面对发妻的去世,嘉庆的心疼得揪到一起,泪水在眼圈里打转,可他不敢让人看到,为了不让泪水流下来,他急忙转身,偷偷地将泪水擦去。转过身来,他和珅贪赃枉法却深受乾隆赏识,乾隆为何不杀和珅?和珅没我不行和珅,一个将贪赃枉法吸烟刻肺的传奇贪官,他身兼数职,用过人的本领爬上了权利的巅峰,而他贪污的财产也如同官职达到顶峰,据说他的家产足以抵得上清王朝国库15年的收入总和。如此一个贪污成