当前位置:首页 » 安卓系统 » android软引用

android软引用

发布时间: 2023-05-19 01:42:03

❶ 获取当前Activity的几种方式

1. 通过RunningTaskInfo的topActivity获取当前Activity实例。通过该种方式获取的Activity,只能保证其已经执行了Activity.onCreate方法,不能保证是否执行了Activity.onResume方法。该方法在api 21以后已经被禁,使用需谨慎。

2. 通过Android 4.0之后提供的ActivityLifecycleCallbacks接口监听当前的Activity实例,可以在onActivityCreated或者onActivityResumed当中获取到。建议在onActivityResumed当中去获取,同时最好以软引用或者弱引用的方式持有,防止OOM。(其中XxxApplication是你的工程Application)

3. 手写Activity管理栈,可以使用Stack或者List等存储纯纯裂做闭已经执行了Activity.onCreate或者Activity.onResume方法的Activity,并相应在Activity.onPause或者Activity.onDestroy中移除。裤铅

4. 反射方式

❷ android缓存硬引用和软引用是什么意思

强引用 SrongReference:
一般我们常用到的引用就是强引用,比如上面提到的引用计数法里面的引用。
软引用 SoftReference:
对于GC来说, SoftReference的强度明显低差竖誉虚段于 SrongReference。 SoftReference修饰的引用,其告诉GC:我是一个 软引用,当内存不足的时候,我指向的这个内存是可以给你释放掉的。我们来看一下android系统中的一个使用实列(纤尺MessageItem.java):

❸ Glide图片加载的用法介绍和三级缓存实现

Glide库是用来实现图片加载的框架,功能强大且易使用,深受大家喜爱。

为啥要做缓存? android默认给每个应用只分配16M的内存,所以如果加载过多的图片,为了 防止内存溢出 ,应该将图片缓存起来。

图片的三级缓存分别是:

1、内存缓存
2、本地缓存
3、网络缓存
其中,内存缓存应优先加载,它速度最快;本地缓存次优先加载,它速度也快;网络缓存不应该优先加载,它走网络,速度慢且耗流量。

最优-优先级:内存缓存 > 本地缓存 > 网络缓存

两个方法实现:根据图片的url去加载图片、在本地和内存中缓存

两个方法实现:设置本地缓存,以及获取本地缓存

两个方法实现:设置内存缓存,获取内存缓存。

如果使用hashmap去存储图片时,当图片越来越多,那么会造成内存溢出,因为是强引用(对于强引用的系统不会回收)

如果改成软引用softReference,在android 2.3 以上的系统,对象会被提前回收。

可以用LruCache来解决上述内存不回收或提前回收的问题。least recentlly use 最少最近使用算法 它会将内存控制在一定的大小内, 超出最大值时会自动回收, 这个最大值开发者自己定。(这个东西没有用过..)

参考链接: https://blog.csdn.net/sinat_20645961/article/details/46325243

❹ 安卓开发中提高安卓程序效率的15小技巧

安卓开发中提高安卓程序效率的15小技巧

对于一个安卓开发者来说,安卓开发中的提高安卓程序效率也是一项重要的内容,到底如何提高安卓程序效率,如何优化安卓的性能呢?以下达内南宁安卓培训部老师介绍了15种优化安卓的性能的小技巧,希望对广大的安卓开发者有所帮助!

1.http用gzip压缩,设置连接超时时间和响应超时时间

http请求按照业务需求,分为是否可以缓存和不可缓存,那么在无网络的环境中,仍然通过缓存的浏览部分数据,实现离线阅读。

2.使用线程池,分为核心线程池和普通线程池,下载图片等耗时任务放袜冲置在普通线程池,避免耗时任务阻塞线程池后,导致所有异步任务都必须等待

3.尽量避免static成员变量引用资源耗费过多的实例,比如Context

4.listview性能优化

1).异步加载图片

item中如果包含有webimage,那么最好异步加载

2).快速滑动时不显示图片

当快速滑动列表时(SCROLL_STATE_FLING),item中的图片或获取需要消耗资源的view,可以不显示出来;而处于其他两种状态(SCROLL_STATE_IDLE和SCROLL_STATE_TOUCH_SCROLL),则将那些view显示出来

3).复用convertView

在getItemView中,判断convertView是否为空,如果不为空,可复用。如果couvertview中的view需要添加listerner,代码一定要在if(convertView==null){}之外告贺。

4).BaseAdapter避免内存溢出

如果BaseAdapter的实体类有属性非常消耗内存,可以将保存到文件;为提高性能,可以进行缓存,并限制缓存大小。

5.对于一个安卓开发者来说,安卓开发中的提高安卓程序效率也是一项重要的内容,到底如何提高安卓程序效率,如何优化安卓的性能呢?以下本文就介绍了15种优化安卓的性能的小技巧,希望对广大的安卓开发者有所帮助!

6.保证Cursor占用的内存被及时的释放掉,而不是等待GC来处理。并且Android明显是倾向于编程者手动的将Cursorclose掉;

7.异步任务,分为核心任务和普通任务,只有核心任务中出现的系统级错误才会报错,异步任务的ui操袜好派作需要判断原activity是否处于激活状态;

8.使用代替强引用,弱引用可以让您保持对对象的引用,同时允许GC在必要时释放对象,回收内存。对于那些创建便宜但耗费大量内存的对象,即希望保持该对象,又要在应用程序需要时使用,同时希望GC必要时回收时,可以考虑使用弱引用。

9.超级大胖子Bitmap及时的销毁(Activity的onDestroy时将bitmap回收,在被UI组件使用后马上进行回收会抛:Canvas:.graphics.Bitmap)设置一定的采样率(有开发者提供的图片无需进行采样,对于有用户上传或第三方的大小不可控图片,可进行采样减少图片所占的内存),从服务端返回图片,建议同时反馈图片的size巧妙的运用软引用drawable对应resid的资源,bitmap对应其他资源任何类型的图片,如果获取不到(例如文件不存在,或者读取文件时跑OutOfMemory异常),应该有对应的默认图片(默认图片放在在apk中,通过resid获取);

10.Drawable中ui组件需要用到的图片是apk包自带的,那么一律用或者,而不要根据resourceid

注意:get((),R.drawable.btn_achievement_normal)该方法通过resid转换为drawable,需要考虑回收的问题,如果drawable是对象私有对象,在对象销毁前是肯定不会释放内存的。

11.复用、回收Activity对象临时的activity及时finish主界面设置为singleTask一般界面设置为singleTop。

12.在onResume时设置该界面的电源管理,在onPause时取消设置。

13.应用开发中自定义View的时候,交互部分,千万不要写成线程不断刷新界面显示,而是根据事件主动触发界面的更新。

14.如果ImageView的图片是来自网络,进行异步加载。

15.位置信息获取用户的地理位置信息时,在需要获取数据的时候打开GPS,之后及时关闭掉。

❺ android中四大引用的区别,强引用,软引用,弱引用和虚引用

四大引用的区别就是内存回收的区别,强引用只要存在没有被销毁,内存就不会被系统回收,软引用在内存严重不足的情况下会被系统回收,弱引用会在系统的内存出现报警(比严重不足的搏世程度基谈肢低)情况下回收,虚引用很容易被回收掉。总的来说就是内存被系统回收的概率从小到大是:虚引用--弱引用--软引侍扮用--强引用

❻ Android 【手撕Glide】--Glide缓存机制(面试)

本文源码解析基于Glide 4.6.1

系列文章
Android 【手撕Glide】--Glide缓存机制
Android 【手撕Glide】--Glide缓存机制(面试)
Android 【手撕Glide】--Glide是如何关联生命周期的?

Glide缓存分为内存缓存和磁盘缓存,其中内存缓存是由弱引用+LruCache组成。

取的顺序是:弱引用、LruCache、磁盘
存的顺序是:磁盘、弱引用、LruCache

这张亲手制作的图片,方便大家更直观的理解缓存机制的整体流程,结合文末总结效果更佳。喜欢的记得点赞!

概述

1、弱引用是由这样一个HashMap维护,key是缓存的key,这个key由图片url、width、height等10来个参数组成;value是图片资源对象的弱引用形式。

2、LruCache是由一个LinkedHashMap维护,根据Lru算法来管理图片。大致的原理是利用linkHashMap链表的特性,把最近使用过的文件插入到列表头部,没使用的图片放在尾部;然后当图片大小到达预先设置的一个阀值的时候 ,按算法删除列表尾部的部分数据。由于篇幅有限,这里不讲解LruCache和DiskLruCache的底层原理,这里推荐一篇 图解LinkedHashMap原理

这是Glide自定义的LruCache

存取原理
取数据
在内存缓存中有一个概念叫图片引用计数器 ,具体来说是在 EngineResource 中定义一个 acquired 变量用来记录图袜指正片被引用的次数,调用 acquire() 方法会让变量加1,调用 release() 方法会让变量减1。

获取图片资源是先从弱引用取缓存,拿到的话,引用计数+1;没有的话从LruCache中拿缓存,拿到的话,引用计数逗枝也是+1,同时把图片从LruCache缓存转移到弱应用缓存池中;再没有的话就通过 EngineJob 开启线程池去加载图片,拿到的话,引用计数也是+1,会把图片放到弱引用。

存数据
很明显,这是加载图片之后的事情。通过 EngineJob 开启线程池去加载图片,取到数据之后,会回调到主线程,把图片存到弱引用。当图片不再使用的时候,比如说暂停请求或者加载完毕或者清除资源时,就会将其从弱引用中转移到告悔 LruCache 缓存池中。 总结一下,就是正在使用中的图片使用 弱引用 来进行缓存,暂时不用的图片使用 LruCache 来进行缓存的功能;同一张图片只会出现在 弱引用 和 LruCache 中的一个。

为什么要引入软引用?
1、分压策略,减少Lrucache 中 trimToSize 的概率。如果正在remove的是张大图,lrucache正好处在临界点,此时remove操作,将延缓Lrucache的 trimToSize 操作;
2 提高效率:弱引用用的是 HashMap ,Lrucache用的是 LinkedHashMap ,从访问效率而言,肯定是 HashMap 更高。

Glide磁盘缓存策略(4.x)

如果在内存缓存中没获取到数据会通过 EngineJob 开启线程池去加载图片,这里有2个关键类: DecodeJob 和 EngineJob 。 EngineJob 内部维护了线程池,用来管理资源加载,当资源加载完毕的时候通知回调; DecodeJob 是线程池中的一个任务。

磁盘缓存是通过 DiskLruCache 来管理的,根据缓存策略,会有2种类型的图片, DATA (原始图片)和 RESOURCE (转换后的图片)。磁盘缓存依次通过 ResourcesCacheGenerator 、 SourceGenerator 、 DataCacheGenerator 来获取缓存数据。 ResourcesCacheGenerator 获取的是转换过的缓存数据; SourceGenerator 获取的是未经转换的原始的缓存数据; DataCacheGenerator 是通过网络获取图片数据再按照按照缓存策略的不同去缓存不同的图片到磁盘上。

Glide缓存分为 弱引用+ LruCache+ DiskLruCache ,其中读取数据的顺序是:弱引用 > LruCache > DiskLruCache>网络;写入缓存的顺序是:网络 --> DiskLruCache--> LruCache-->弱引用

内存缓存分为弱引用的和 LruCache ,其中正在使用的图片使用弱引用缓存,暂时不使用的图片用 LruCache缓存,这一点是通过 图片引用计数器(acquired变量)来实现的,详情可以看内存缓存的小结。

磁盘缓存就是通过DiskLruCache实现的,根据缓存策略的不同会获取到不同类型的缓存图片。它的逻辑是:先从转换后的缓存中取;没有的话再从原始的(没有转换过的)缓存中拿数据;再没有的话就从网络加载图片数据,获取到数据之后,再依次缓存到磁盘和弱引用。

参考:
面试官:简历上最好不要写Glide,不是问源码那么简单
原来面试的时候写精通Glide,这样问我这样答

❼ Android基础 (11) PopupWindow详解

(1)PopupWindow的使用
(2)自定义一个PopupWindow
(3)PopupWindow的源码分析
(4)AlertDialog,popupWindow,Activity区别
(5)Activity-Window-View三者的差别

Android的对话框有两种:PopupWindow和AlertDialog。它们的不同点在于:

PopupWindow的位置按照有无偏移分,可以分为偏移和无偏移两种;按照参照物的不同,可以分为相对于某个控件(Anchor锚)和相对于父控件。具体如下:
showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移。

使用详述: https://blog.csdn.net/xiaanming/article/details/9121383

这里的WRAP_CONTENT可以换成fill_parent 也可以是具体的数值,它是指PopupWindow的大小,也就是contentView的大小,注意popupWindow根据这个大小显示你的View,如果你的View本身是从xml得到的,那么xml的第一层view的大小属性将被忽略。相当于popupWindow的width和height属性直接和第一层View相对应。

执行了一个attachToAnchor,意思是PopupWindow类似一个锚挂在目标view的下面,这个函数主要讲xoff、yoff(x轴、y轴偏移值)、gravity(比如Gravity.BOTTOM之类,指的是PopupWindow放在目标view哪个方向边缘的位置)这个attachToAnchor有点意思,通过弱引用保存目标view和目标view的rootView(我们都知道:通过弱引用和软引用可以防止内存泄漏)、这个rootview是否依附在window、还有保存偏差值、gravity

PopupWindow通过为传入的View添加一层包裹的布局,并重写该布局的点击事件,实现点击PopupWindow之外的区域PopupWindow消失的效果

封装库可前往:#### https://github.com/yangchong211/YCDialog

❽ Android App内存优化

内存优化就是对内存问题的一个预防和解决,做内存优化能让应用挂得少、活得好和活得久。

挂的少:
“挂”指的是 Crash,内存问题导致 Crash 的具体表现就是内存溢出异常 OOM。

活得好:
活得好指的是使用流畅,Android 中造成界面卡顿的原因有很多种,其中一种就是由内存问题引起的。内存问题之所以会影响到界面流畅度,是因为垃圾回收(GC,Garbage Collection),在 GC 时,所有线程都要停止,包括主线程,当 GC 和绘制界面的操作同时触发时,绘制的执行就会被搁置,导致掉帧,也就是界面卡顿。

活得久:
活得久指的是我们的应用在后台运行时不会被干掉。Android 会按照特定的机制清理进程,清理进程时优先会考虑清理后台进程。清理进程的机制就是LowMemoryKiller。在 Android 中不同的进程有着不同的优先级,当两个进程的优先级相同时,低杀会优先考虑干掉消耗内存更多的进程。也就是如果我们应用占用的内存比其他应用少,并且处于后台时,我们的应用能在后台活下来,这也是内存优化为我们应用带来竞争力的一个直接体现。

内存占用是否越少越好?
当系统 内存充足 的时候,我们可以多用 一些获得更好的性能。当系统 内存不足 的时候,我们希望可以做到 ”用时分配,及时释放“。内存优化并不能一刀切。

我们都知道,应用程序的内存分配和垃圾回收都是由Android虚拟机完成的,在Android 5.0以下,使用的是Dalvik虚拟机,5.0及以上,则使用的是ART虚拟机。
Android虚拟机Dalvik和ART

1、内存区域划分

详细请看以下两篇文章(建议全看):
java内存四大区_JVM内存区域划分
Android 内存机制

2、内存回收

垃圾收集的标记算法(找到垃圾):

垃圾收集算法(回收垃圾):

引用类型:强引用、软引用、弱引用、虚引用

对象的有效性=可达性+引用类型

JAVA垃圾回收机制-史上最容易理解看这一篇就够了
Android:玩转垃圾回收机制与分代回收策略

android中还存在低杀机制,这种情况属于系统整机内存不足,直接把应用进程杀掉的情况。

Android后台杀死系列:LowMemoryKiller原理

1、内存溢出
系统会给每个App分配内存空间也就是heap size值,当app占用的内存加上申请的内存超过这个系统分配的内存限额,最终导致OOM(OutOfMemory)使程序崩溃。

通过命令 getprop |grep dalvik.vm.heapsize 可以获取系统允许的最大
注意:在设置了heapgrowthlimit的状况下,单个进程可用最大内存为heapgrowthlimit值。在android开发中,若是要使用大堆,须要在manifest中指定android:largeHeap为true,这样dvm heap最大可达heapsize。
关于heapsize & heapgrowthlimit

2、内存泄漏
Android系统虚拟机的垃圾回收是通过虚拟机GC机制来实现的。GC会选择一些还存活的对象作为内存遍历的根节点GC Roots,通过对GC Roots的可达性来判断是否需要回收。内存泄漏就是 在当前应用周期内不再使用的对象被GC Roots引用,造成该对象无法被系统回收,以致该对象在堆中所占用的内存单元无法被释放而造成内存空间浪费,使实际可使用内存变小。简言之,就是 对象被持有导致无法释放或不能按照对象正常的生命周期进行释放。
Android常见内存泄漏汇总

3、内存抖动
指的是在短时间内大量的新对象被实例化,运行时可能无法承载这样的内存分配,在这种情况下就会导致垃圾回收事件被大量调用,影响到应用程序的UI和整体性能,最终可能导致卡顿和OOM。
常见情况:在一些被频繁调用的方法内不断地创建对象。例如在View 的onDraw方法内new 一些新的对象。

注意内存抖动也会导致 OOM,主要原因有如下两点:

1、Android Studio Profiler

作用

优点

内存抖动问题处理实战

理解内存抖动的概念的话,我们就能明白只要能找到抖动过程中所产生的对象及其调用栈,我们就能解决问题,刚好Android Studio 的Porfiler里面的Memory工具就能帮我们记录下我们操作过程中或静止界面所产生的新对象,并且能清晰看到这些对象的调用栈。

选择Profile 中 的Memory ,选择 Record Java/Kotlin allocations,再点击Record开始记录, Record Java/Kotlin allocations 选项会记录下新增的对象。

操作完成之后,点击如图所示的红脑按钮,停止记录。

停止记录后,我们就可以排序(点击 Allocations可以排序)看看哪些对象或基本类型在短时间被频繁创建多个,点击这些新增的对象就可以看到它的完成的调用链了,进而就找找到导致内存抖动的地方在哪里了。

2、利用DDMS 和 MAT(Memory Analyzer tool)来分析内存泄漏

我们利用工具进行内存泄漏分析主要是用对比法:
a.先打开正常界面,不做任何操作,先抓取一开始的堆文件。
b.一顿胡乱操作,回到原来操作前的界面。主动触发一两次GC,过10秒再抓取第二次堆文件。
c.通过工具对比,获取胡乱操作后新增的对象,然后分析这些新增的对象。

DDMS作用:抓取堆文件,主动触发GC。(其实也是可以用Android Studio 的Profile里面的Memory工具来抓取堆文件的,但是我这边在利用Profile 主动触发gc 的时候会导致程序奔溃,也不知道是不是手机的问题,所以没用Android Studio的Profiler)

MAT作用:对堆文件进行对比,找到多出的对象,找到对象的强引用调用链。

以下是详细的过程:

步骤1.打开DDMS,选择需要调试的应用,打开初始界面,点击下图的图标(Dump Hprof File)先获取一次堆文件。

步骤2.对应用随便操作后,回到一开始的界面,先多触发几次GC ,点击下图的图标(Cause Gc)来主动触发GC,然后再次点击 Dump Hprof File 图标来获取堆文件。

步骤3.通过Android Studio Profile 或者 DDMS mp 的堆文件无法在MAT 打开,需要借助android sdk包下的一个工具hprof-conv.exe来转换。

格式为 hprof-conv 旧文件路径名 要转换的名称;
例如:hprof-conv 2022-04-13_17-54-40_827.hprof change.hprof

步骤4.把两份堆文件导入MAT,然后选择其中第二次获取的堆文件,点击 如图所示的 Histogram查看。

步骤5.点击下图图标,Compare To Another Heap Dump ,选择另一份堆文件。

6.会得出下图所示的 Hitogram 展示,我们主要看Objects 这一列。 如下图所示 “+ 2” 则代表前面两份堆文件对比,这个对象多了两个,我们主要就是要分析这些多了出来,没有被回收的对象。

7.加入我们从增加的对象中,看到了MainActivity ,则需要从一开始打开的Hitogram 展示里面找到这个对象的调用栈。如下图所示,搜索MainActivity

8.看到下图所示解雇,然后鼠标右键点击下图红色圈圈着的MainActivity ,选择 Merger Shortest Paths to Gc Roots ,再选择 exclude all phantom/weak/soft etc.references ,就可以看到这个MainActivity 对象的强引用链,至此我们就可以找到MainActivity对象是被什么引用导致无法回收了。

3、内存泄露检测神器之LeakCanary(线下集成)

自行学习了解,接入简单,使用简单,基本可以解决大部分内存泄漏问题。
github地址 : https://github.com/square/leakcanary/
学习地址 : https://square.github.io/leakcanary/changelog/#version-22-2020-02-05

针对内存抖动的建议:

针对内存泄漏问题的建议:

针对内存溢出问题的建议(主要就是要减少内存占用):

建议参考:
深入探索 Android 内存优化(炼狱级别)

对于 优化的大方向,我们应该优先去做见效快的地方,主要有以下三部分:内存泄漏、内存抖动、Bitmap。完善监控机制也是我们的重点,能帮助我们对内存问题快速分析和处理。

参考:
深入探索 Android 内存优化(炼狱级别)

❾ Android 内存回收机制

新生代的内存区域又被分成三部分,分别是Eden、s0、s1,在hotspot中它们的默认是比例是8:1:1,为什么是这个比例下面会解释。每次分配新对象都是从Eden中分配,新生代的gc过程是,通过gc root对象(gc root对象包括:在栈帧中的对象、native栈中的对象、静态对象)标记存活的对象,并且把存活的对象拷贝到s0中然后清空Eden,接下来的gc又会把Eden和s0存活的对象拷贝到s1中,s0和是s1总有一个是空闲的,gc过程就是把Eden和其中一个s的存活对象拷贝到另一个s中,然后清空s和Eden。为什么Eden:s0:s1是8:1:1呢?那是因为新生代对象经过一次gc后存活的概率只有5%左右,之前IBM统计过,正是因为新生代经过gc后存活的对象很少,才会使用拷贝擦除这种方法。gc最快的方法就是把没有被gc root对象直接引用或者间接引用的对象标记为无效,但是这样势必会造成大量的内存碎片,所以综合考虑最终在新生代使用拷贝擦除这种算法

在新生代中经过多次gc后仍然存活的对象则会晋升为老年代对象。老年代对象的gc比新生代更耗时。
老年代的gc过程是:

由于Android作为一个终端,需要快速的响应用户的操作,而gc过程又要暂停所有的线程,所以必须要保证的gc的帆段核时间不会太长。在Android中应用启动的时候一般会分配一段内存作为初始内存,在应用燃银的运行过程需要创建一个新对象,而初始分配的内存空间已经无法提供足够的内存,此时就会触发gc,如果gc过后还是没有足够内存则会对堆内存进行扩容,扩容到最大值后还是没有提供足够的内存则会再进行一次gc,这次gc会把软引用也清空,如果仍然没有足够的内存就抛出oom。

总结起来 Android系统不会一次性就把堆内存分配给应用进程,这态掘样会导致gc的时间很长,用户的操作长时间得不到响应,而是分步给应用进程的堆内存进行扩容直到最大限制值

❿ Android内存优化三:内存泄漏检测与监控

Android内存优化一:java垃圾回收机制
Android内存优化二:内存泄漏
Android内存优化三:内存泄漏检测与监控
Android内存优化四:OOM
Android内存优化五:Bitmap优化

Memory Profiler 是 Profiler 中的其中一个版块,Profiler 是 Android Studio 为我们提供的性能分析工具,使用 Profiler 能分析应用的 CPU、内存、网络以及电量的使用情况。

进入了 Memory Profiler 界面。

点击 Record 按钮后,Profiler 会为我们记录一段时间内的内存分配情况。

在内存分配面板中,通过拖动时间线来查看一段时间内的内存分配情况

通过搜索类或者报名的方式查看对象的使用情况

使用Memory Profiler 分析内存可以查看官网: 使用内存性能分析器查看应用的内存使用情况

对于内存泄漏问题,Memory Profiler 只能提供一个简单的分析,不能够确认具体发生问题的地方。

而 MAT 就可以帮我们做到这一点,它是一款功能强大的 Java 堆内存分析工具,可以用于查找内存泄漏以及查看内存消耗情况。

as 生成hprof文件无法被mat识别,需要进行转换

使用hprof-conv进行转换,hprof-conv位于sdkplatform-tools

ps:as导出hprof前最好先gc几次,可排除一些干扰

Histogram 可以列出内存中的对象,对象的个数以及大小; Dominator Tree 可以列出那个线程,以及线程下面的那些对象占用的空间; Top consumers 通过图形列出最大的object; Leak Suspects 通过MA自动分析泄漏的原因。

Shallow Heap就是对象本身占用内存的大小,不包含其引用的对象内存,实际分析中作用不大。常规对象(非数组)的ShallowSize由其成员变量的数量和类型决定。数组的shallow size有数组元素的类型(对象类型、基本类型)和数组长度决定。对象成员都是些引用,真正的内存都在堆上,看起来是一堆原生的byte[], char[], int[],对象本身的内存都很小。

Retained Heap值的计算方式是将Retained Set(当该对象被回收时那些将被GC回收的对象集合)中的所有对象大小叠加。或者说,因为X被释放,导致其它所有被释放对象(包括被递归释放的)所占的heap大小。

Path To GC Roots -> exclude all phantim/weak/soft etc. references:查看这个对象的GC Root,不包含虚、弱引用、软引用,剩下的就是强引用。从GC上说,除了强引用外,其他的引用在JVM需要的情况下是都可以 被GC掉的,如果一个对象始终无法被GC,就是因为强引用的存在,从而导致在GC的过程中一直得不到回收,因此就内存泄漏了。

List objects -> with incoming references:查看这个对象持有的外部对象引用

List objects -> with outcoming references:查看这个对象被哪些外部对象引用

使用对象查询语言可以快速定位发生泄漏的Activity及Fragment

使用 MAT 来分析内存问题,效率比较低,为了能迅速发现内存泄漏,Square 公司基于 MAT 开源了 LeakCanary ,LeakCanary 是一个内存泄漏检测框架。

集成LeakCanary后,可以在桌面看到 LeakCanary 用于分析内存泄漏的应用。

当发生泄漏,会为我们生成一个泄漏信息概览页,可以看到泄漏引用链的详情。

LeakCanary 会解析 hprof 文件,并且找出导致 GC 无法回收实例的引用链,这也就是泄漏踪迹(Leak Trace)。

泄漏踪迹也叫最短强引用路径,这个路径是 GC Roots 到实例的路径。

LeakCanary 存在几个问题,不同用于线上监控功能

线上监控需要做的,就是解决以上几个问题。

各大厂都有开发线上监控方案,比如快手的 KOOM ,美团的 Probe ,字节的 Liko

快手自研OOM解决方案KOOM今日宣布开源

总结一下几点:

通过无性能损耗的 内存阈值监控 来触发镜像采集。将对象是否泄漏的判断延迟到了解析时

利用系统内核COW( Copy-on-write ,写时复制)机制,每次mp内存镜像前先暂停虚拟机,然后fork子进程来执行mp操作,父进程在fork成功后立刻恢复虚拟机运行,整个过程对于父进程来讲总耗时只有几毫秒,对用户完全没有影响。

热点内容
我的世界lce服务器剪辑 发布:2025-02-13 14:40:50 浏览:624
phpsftp上传 发布:2025-02-13 14:35:43 浏览:273
c学生管理系统数据库 发布:2025-02-13 14:21:41 浏览:122
传奇添加会员脚本 发布:2025-02-13 14:20:50 浏览:205
微信开发平台源码 发布:2025-02-13 14:14:20 浏览:613
安卓大屏屏幕休眠是什么意思 发布:2025-02-13 14:13:28 浏览:464
脚本的参数设置 发布:2025-02-13 14:11:57 浏览:863
androidtexture 发布:2025-02-13 14:11:57 浏览:393
怎么取消网络密码怎么设置 发布:2025-02-13 14:11:54 浏览:426
我的世界电脑手机等价科技服务器 发布:2025-02-13 14:06:06 浏览:244