Android内存优化的常用工具与手段

内存问题相对比较隐蔽,表现并不明显。

内存问题难以定位,出现问题的地方往往只是表现的地方,真正的原因难以收集。

内存优化的内容其实非常多而复杂,我们可以尝试从以下思路去了解:

要了解内存问题,我们首先要了解为什么要做内存优化?

同时需要了解一些内存优化的背景知识,如垃圾回收机制。

我们需要了解一些内存优化的常用工具与手段。

图片是内存优化的重点,我们需要重点了解下图片优化的知识点。

内存问题的一个直接体现是OOM,我们还需要了解下OOM治理的一些手段。

所以我们可以轻松得出本文的主要内容:

为什么要做内存优化?

android内存优化的一些背景知识。

android内存优化的常用工具与手段。

怎么做图片内存优化?

怎么做OOM线上监控?

本文主要内容思维导图如下:

1、为什么要做内存优化?

要回答这个问题,我们首先应该明确需求,当我们去做内存优化时是为了什么。

1.1降低OOM率

做内存优化的一个常见原因是为了降低OOM率。

申请内存过多而没有及时释放,常常就会导致OOM。

引起OOM的原因有多种,在后面我们再细谈。

1.2减少卡顿

Android中造成界面卡顿的原因有很多种,其中一种就是由内存问题引起的。

内存问题之所以会影响到界面流畅度,是因为垃圾回收。

在GC时,所有线程都要停止,包括主线程。当GC和绘制界面的操作同时触发时,绘制的执行就会被搁置,导致掉帧,也就是界面卡顿。

Android会按照特定的机制清理进程,清理进程时优先会考虑清理后台进程,如果某个应用在后台运行并且占用的内存更多,就会被优先清理掉。

我们通常希望App能尽量存活的久一点,所以内存不再使用时应该尽快释放。

2、android内存优化的一些背景知识

Java内存回收主要包括以下内容:

强软弱虚4种引用类型。

用于GC回收的垃圾回收算法。

这些都是很常见的知识点了,这里也就不缀述了,如果想要了解更多细节的同学可参考:Java垃圾回收机制。

2.2什么是内存泄漏?

内存泄漏的表现就是可用内存逐渐减少,无法被回收的内存逐渐累积,直到应用无更多可用内存可申请时,就会导致内存溢出。

内存泄漏的直接原因是长生命周期的对象引用了短生命周期的对象,导致短生命周期对象无法回收。

常见的引起内存泄漏的原因有:

非静态内部类持有了外部引用。

资源没有及时释放。

2.3什么是内存抖动?

内存抖动意味着频繁的创建对象与回收,容易触发GC,而当GC时所有线程都会停止,因此可能导致卡顿。

为了避免内存抖动,我们应该避免以下操作:

尽量避免在循环体中创建对象。

尽量不要在自定义View的onDraw()方法中创建对象,因为这个方法会被频繁调用。

对于能够复用的对象,可以考虑使用对象池把它们缓存起来。

2.4什么是内存溢出?

引起OOM的原因可能有多种,主要可以分为以下几类:

关于OOM治理及线上监控等,后面会详细介绍。

3、android内存优化的常用工具与手段

3.1MemoryProfiler

使用Memory可以检测以下功能:

查看内存曲线及内存占用情况。

可以定位是否存在内存抖动问题。

堆转储(DumpJavaHeap)可检测出内存泄漏的对象。

关于MemoryProfiler的具体使用就不在此缀述了,想要了解的可参考:什么是MemoryProfiler?

3.2MemoryAnalyzerTool

比起MemoryProfiler,MAT使用起来更加麻烦,同时现在MemoryProfiler功能也越来越强大了,所以我现在已经很少使用MAT了。

如果想要更多地了解MAT,也可以参考:什么是MemoryAnalyzerTool。

3.3LeakCanary检测内存泄漏

相比MemoryProfiler与MAT,LeakCanary在使用上更加简便。

只需要在项目中添加依赖,即可自动地检测内存泄漏并报警,使用起来非常方便。

LeakCanary有以下几个特点:

不需要手动初始化。

可自动检测内存泄漏并通过通知报警。

不能用于线上。

LeakCanary检测流程如下

3.4内存优化的一些常规手段

内存优化的一些细节问题可以在开发时避免,下面介绍一些常规的内存优化手段。

1)、使用LargeHeap属性增加最大可用内存。

2)、在系统触发资源紧张回调时,主动删除缓存。

3)、使用优化过后的集合:如SparseArray类等。

4)、谨慎使用SharedPreference,SP会在应用初始化时将所有内容加载到内存中,所以不应该存放比较大的内容。

5)、谨慎使用外部库,引入时需要明确不会对应用性能造成大的影响。

6)、业务架构设计要合理,抽象可以优化代码的灵活性和可维护性,但是抽象也会带来其他成本,应权衡使用。

这些细节问题其实都很普通,如果平时注意到了,相信对应用的内存一定有所帮助。

4、怎么做图片内存优化?

内存优化应该优先去做见效快的地方,图片内存优化是内存优化的重点,可能一张图片没有回收就会造成几M内存的浪费。

4.1常规的图片内存优化方法

我们都知道,图片所占内存=宽高一像素占用内存。

所以优化图片内存主要有以下几个思路:

缩放减小宽高。

减少每个像素所占用的内存。

内存复用,避免重复分配内存。

对于大图,可以采取局部加载的策略。

4.1.1减少图片宽高

有时图片宽高为200*200,而View宽高为100*100,这种时候如果展示200*200的图片没有意义,应该对图片进行缩放。

这种情况一般通过inSampleSize实现。

BitampFactory.Optionsoptions=newBitmapFactory.Options();

//设置为4就是宽和高都变为原来1/4大小的图片

options.inSampleSize=4;

BitmapFactory.decodeSream(is,null,options);

4.1.2减少每个像素所占用的内存

RGB_565:仅存储RGB通道,每个像素占2个字节,对Bitmap色彩没有高要求,可以使用该模式;

ARGB_4444:已弃用,用ARGB_8888代替;

ARGB_8888:每个像素占用4个字节,保持高质量的色彩保真度,默认使用该模式;

RGBA_F16:每个像素占用8个字节,适合宽色域和HDR;

HARDWARE:一种特殊的配置,减少了内存占用同时也加快了Bitmap的绘制。

每个等级每个像素所占用的字节也都不一样,所存储的色彩信息也不同。同一张100像素的图片,ARGB_8888就占了400字节,RGB_565才占200字节。

所以在某些场景中,修改图片格式可以达到减少一半内存的效果。

4.1.3内存复用,避免重复分配内存

Bitmap所占内存比较大,如果我们频繁创建与回收Bitmap,那么很容易造成内存抖动,所以我们应该尽量复用Bitmap内存。

在Android3.0(API级别11)开始,系统引入了BitmapFactory.Options.inBitmap字段。如果设置了此选项,那么采用Options对象的解码方法会在生成目标Bitmap时尝试复用inBitmap,这意味着inBitmap的内存得到了重复使用,从而提高了性能,同时移除了内存分配和取消分配。

不过inBitmap的使用方式存在某些限制,在Android4.4(API级别19)之前系统仅支持复用大小相同的位图,4.4之后只要inBitmap的大小比目标Bitmap大即可。

4.1.4大图局部加载策略

对于图片加载还有种情况,就是单个图片非常巨大,并且还不允许压缩。比如显示:世界地图、清明上河图、微博长图等。

首先不压缩,按照原图尺寸加载,那么屏幕肯定是不够大的,并且考虑到内存的情况,不可能一次性整图加载到内存中。

所以这种情况的优化思路一般是局部加载,通过BitmapRegionDecoder来实现。

BitmapRegionDecoderbitmapRegionDecoder=BitmapRegionDecoder.newInstance(inputStream,false);

BitmapFactory.Optionsoptions=newBitmapFactory.Options();

Bitmapbitmap=bitmapRegionDecoder.decodeRegion(newRect(width/2-100,height/2-100,width/2+100,height/2+100),options);

mImageView.setImageBitmap(bitmap);

4.1.5小结

上面所说的这些关于Bitmap的内存优化策略其实都比较简单,而且我们在开发中可能很少用到

因为我们常用的图片框架比如Glide已经将这些都封装在里面了,所以一般情况下我们加载图片时不需要做这些特殊操作。

关于Glide对于加载图片都做了哪些优化,有兴趣的同学可以参考:【带着问题学】Glide做了哪些优化?

4.2图片兜底策略

通过这种方式可以方便地解决因Activity导致的图片泄漏问题。

4.3线上大图监控方案

当运营在线上配置了不合理大小的图片时,如果我们及时发现,也会带来内存问题。

如果图片本身大小就不合理,我们在这个基础上谈图片优化也没有什么意义,因此大图监控这也是个比较常见的需求。

下面介绍几种大图监控的方案:

4.3.1ArtHook方案

这种方案的优点在于:

侵入性极低,一次初始化配置即可hook全局的目标View控件。

可以获取代码调用堆栈,方便开发者快速定位。

而缺点则在于:

兼容性存在问题,使用了hook系统API,不能用于线上。

4.3.2BaseActivity方案

大部分应用工程在业务发展的过程中都会沉淀封装自己的BaseActivity,通过在BaseActivityonDestroy中动态地检测各个View控件,从而获知图片加载情况。

classBaseActivity:Activity(){

funonDestory(){

if(isOpenCheckBitmap){

checkBitmapFromView()

}

funcheckBitmapFromView(){

//1、遍历activity中的各个View控件

//2、获取View控件加载的Bitmap

//3、对比Bitmap宽高与View宽高

兼容性强,无任何反射。

加入简单,没有什么复杂逻辑。

缺点在于:

侵入性太强,需要修改BaseActivity。

BaseActivity.onDestory本身可能被重写,并不安全。

4.3.3ASM方案

该方案在编译流程进行插桩,通过匹配setImageBitmap、setBackground等关键方法,插入Bitmap大小检测逻辑。

这种方案优点在于:

编译时期插桩,对开发过程无侵入性。

通过插桩的方式打点,可能会增加编译期耗时。

ASM代码维护成本较高,使用起来不是那么方便。

4.3.4registerActivityLifecycleCallback方案

通过registerActivityLifecycleCallback监听Activity生命周期,在onStop时进行Bitmap大小检测的逻辑。

privatefunregisterActivityLifecycleCallback(application:Application){

application.registerActivityLifecycleCallbacks(object:

Application.ActivityLifecycleCallbacks{

overridefunonActivityStopped(activity:Activity){

checkBitmapIsTooBig(childViews)

})

这种方案对原始代码无侵入性,同时使用起来比较简单,也没有兼容性问题,应该属于比较良好的方案。

详细实现可见:BitmapCanary诞生。

5、怎么做OOM线上监控?

上文我们介绍了,可以使用LeakCanary在线下监测内存泄漏,但是LeakCanary只能在线下使用,有以下问题:

线下场景能跑到的场景有限,很难把所有用户场景穷尽。碰到线上问题难以定位。

检测过程需要主动触发GC,Dump内存镜像造成app冻结,造成测试过程中体验不好。

适用范围有限,只能定位Activity&Fragment泄漏,无法定位大对象、频繁分配等问题。

hprof文件过大,如果整体上传的话需要耗费很多资源。

下面我们就介绍一下快手开源的线上OOM监控框架KOOM。

5.1线上OOM监控框架KOOM介绍

上面我们介绍了LeakCanary不能用于线上监控的原因,所以要实现线上监控功能,就需要解决以下问题:

1、监控

主动触发GC,会造成卡顿

2、采集

Dumphprof,会造成app冻结

Hprof文件过大

3、解析

解析耗时过长

解析本身有OOM风险

其核心流程为三部分:

监控OOM,发生问题时触发内存镜像的采集,以便进一步分析问题。

采集内存镜像,学名堆转储,将内存数据拷贝到文件中,以下简称dumphprof。

5.2KOOM解决GC卡顿

LeakCanary通过多次GC的方式来判断对象是否被回收,所以会造成性能损耗。

koom通过无性能损耗的内存阈值监控来触发镜像采集,具体策略如下:

1、Java堆内存/线程数/文件描述符数突破阈值触发采集。

2、Java堆上涨速度突破阈值触发采集。

3、发生OOM时如果策略1、2未命中触发采集。

4、泄漏判定延迟至解析时。

我们并不需要在运行时判定对象是否泄漏,以Activity为例,我们并不需要在运行时判定其是否泄漏,Activity有一个成员变量mDestroyed,在onDestory时会被置为true,只要解析时发现有可达且mDestroyed为true的Activity,即可判定为泄漏。

通过将泄漏判断延迟至解析时,即可解决GC卡顿的问题。

5.3KOOM解决Dumphprof冻结app

利用Copy-on-write机制,fork子进程dump内存镜像,可以完美解决这一问题,fork成功以后,父进程立刻恢复虚拟机运行,子进程dump内存镜像期间不会受到父进程数据变动的影响。

流程如下图所示:

KOOM随机采集线上真实用户的内存镜像,普通dump和fork子进程dump阻塞用户使用的耗时如下:

可以看出,基本可以做到无感知的采集内存镜像。

5.4KOOM解决hprof文件过大

因此需要对hprof进行裁剪,只保留分析OOM必须的数据,另外,裁剪还有数据脱敏的好处,只上传内存中类与对象的组织结构,并不上传真实的业务数据(诸如字符串、byte数组等含有具体数据的内容),保护用户隐私。

裁剪hprof文件涉及到对hprof文件格式的了解,这里就不缀述了。

5.5KOOM解决hprof解析的耗时与OOM

解析hprof文件,对关键对象进行可达性分析,得到引用链,是解决OOM最核心的一步,之前的监控和dump都是为解析做铺垫。

解析分两种,一种是上传hprof文件由server解析,另一种是在客户端解析后上传报告(通常只有几KB)。

KOOM选择了端上解析,这样做有两个好处:

节省用户流量。

利用用户闲时算力,降低server压力,这样也符合分布式计算理念。

1、哪些对象需要分析,全部分析性能开销太大,很难在端上完成,并且问题没有重点也不利于解决。

2、性能优化,作为一个debug组件,要在不影响用户体验的情况下完成解析,对性能有非常高的要求。

5.5.1关键对象判定

Activity/fragment泄露判定即为第一种:

对于强可达的activity对象,其mDestroyed值为true时(onDestroy时赋值),判定已经泄露。

类似的,对于fragment,当mCalled值为true且mFragmentManager为null时,判定已经泄露。

Bitmap/window/array/sufacetexture判定为第二种。

5.5.2性能优化

详细流程就不在这里缀述了,详情可见:KOOM解析性能优化。

5.6KOOM使用

KOOM目前已经开源,开源地址:

直接参照接入指南接入即可,当发现内存超过阈值或者发生OOM时,就会触发采集内存快照,对hprof文件进行裁剪并分析后得到报告。

KOOM的报告是json格式,并且大小在KB级别,样式如下所示:

大概包括以下信息:

一些可能泄漏的类信息。

泄漏原因,gcRoot,泄漏实例数量等。

泄漏对象的引用链,方便定位问题。

可见KOOM上传的数据量并不太大,但相对准确,非常便于我们分析线上数据。

5.7小结

本章主要介绍了线上监控OOM的开源框架KOOM。

其实线上监控OOM的框架各大厂都有开发,比如美团的Probe,字节的Liko。

总结

对于优化的大方向,我们应该优先去做见效快的地方,主要有以下几个部分:

内存泄漏。

内存抖动。

Bitmap大图监控。

OOM线上监控。

我们还介绍了内存优化的多种实用工具:

可以使用Profile,MAT在开发时定位内存抖动内存泄漏问题。

线下开发、回归、Monkey、压测等环节可以自动集成LeakCanary检测内存泄漏;

图片加载是内存优化的重点,我们可以结合图片兜底策略与线上大图监控,优化图片内存问题。

线上OOM时通过KOOM监测,内存超出阈值时主动dump内存快照,通过上传分析结果精准。分析OOM问题。

内存优化是个复杂的过程,我们在做内存优化的过程中,需要结合多种工具,线上线下结合,系统化地配合来定位与解决问题。

作者:RicardoMJiang

责任编辑:haq

浏览量

原文标题:吹爆系列:Android内存还可以这样优化!

下载发烧友APP

电子发烧友观察

长沙市望城经济技术开发区航空路6号手机智能终端产业园2号厂房3层(0731-88081133)

THE END
1.常用工具图片大全常用工具高清图片下载共4 个 常用工具图片 立即下载 白底一把剪刀 立即下载 整齐排列的工具墙常用五金工具挂在钉板上的五金工具 立即下载 从厨房工作台上的工具箱中取出扳手从厨房工作台上的工具箱中取出扳手的截图 立即下载 黑色桌子上的工具工具箱和板移植修复颅骨工具 觅知网提供大量常用工具图片,常用工具高清图片在线下载。更...https://www.51miz.com/so-tupian/2988460.html
2.常用工具工具箱图片居家生活生活方式常用工具工具箱图片,常用工具工具箱图片 工具 工具箱 工具组合 摄影 实物摄影 产品摄影 生活百科 生活素材 72DPI JPG 摄影图,图行天下素材网图片编号:20200923025544079658https://www.photophoto.cn/pic/39013712.html
3.常用工具图标图片常用工具图标素材常用工具图标模板免费下载六图网为您提供常用工具图标设计作品免费下载服务,您还可以找到常用工具图标图片、常用工具图标素材、常用工具图标模板等设计素材,我们为您提供常用工具图标图片下载,常用工具图标模板下载、常用工具图标素材下载等服务!https://www.16pic.com/sucai/5486325.html
4.32种免费常用工具,图片处理工具文库下载系统优化...前面分享了一个有70多个工具的工具箱,不过那个工具箱大部分是非常专业的一些软件,我们不会经常用到。今天盘哥又来分享一个目前拥有32种常用工具的工具箱,这个相信很多人会用到。工具箱内所有软件都是免费的。 软件简介 黑科技工具箱是一款集成32种常用工具于一身的免费工具箱,内置截图工具、图片识别文字、图片器水...https://www.cnblogs.com/dbdd/p/13065069.html
5.分享‖互联网工作常用的32大类工具问卷星(自己常用的调查问卷工具,制作功能方便快捷) 金数据https://jinshuju.net 9、在线图形设计工具 创客贴(PPT、海报、微信朋友圈封面、邀请函、社交图片) 优界网(主要是海报背景图,收录的背景作品) 10、GIF制作工具 GIFcam(最常用) http://kotaiguchi-gif.tumblr.com/(特点将汉字和立体空间结合起来,营造出古...https://www.jianshu.com/p/0718db9fc1c5
6.226个产品运营常用网站工具推荐青瓜传媒226个产品、运营常用网站工具推荐 做了些工具及干货网站汇总,希望对小伙伴们有帮助。 一、运营及产品经理社区 1.PMCAFF:http://www.pmcaff.com/site/feed 2.人人都是产品经理:http://www.woshipm.com/ 3.产品100:http://www.chanpin100.com/https://www.opp2.com/200214.html
7.ImageTuner常用图片格式 (JPEG, BMP, PNG, GIF, TIFF, PCX 等) 数码相机 RAW 格式 (CRW, CR2, RAW, NEF, DCR, X3F, ORF 等) 写在后面: Image Tuner 对图片的各种处理功能丰富实用,其界面也非常直观简单,即便是新手们也能轻易上手。免费+体积小巧,对于有批量图像调整需求的人来说,绝对是一款值得收藏的好工具。 https://www.iplaysoft.com/image-tuner.html
1.多功能小工具价格图片品牌怎么样京东JD.COM是国内专业的多功能小工具网上购物商城,提供多功能小工具价格,报价,参数,评价,图片,品牌等信息.买多功能小工具,上京东就购了.https://www.jd.com/chanpin/1401828.html
2.常用工具图片专题,常用工具下载常用工具图片专题,常用工具图片下载,昵图网:图片共享和图片交易中心https://www.nipic.com/zhuanti/2037068.html
3.五金工具有哪些?各行各业常用的五金工具清单大全→MAIGOO知识五金工具是指铁、钢、铝等金属物质经过锻炼、压延、切割等物理动作后被加工成各种金属元件。五金工具有很多种类,按我们常见的分有手动工具、电动工具、液压工具、气动工具、金刚石工具、测量工具、焊接工具、切削工具、起重工具、防爆工具、劳动防护工具11大类。下面,我们就来详细了解不同五金工具的特点。 手动工具 手...https://m.maigoo.com/goomai/186551.html
4.常用工具常用工具常用工具 SPSS:SPSS是世界上最早的统计分析软件,是目前国际学术界风靡的研究工具,能通过数据统计揭示不同事物之间的联系,发现规律,被广泛应用于人文社会科学研究领域。SPSS软件具有强大的数据分析功能,并且界面友好、操作简单,广泛的应用于管理决策、市场分析、医学统计、金融等专业的统计分析。面对大量的市场调查、统计...http://hep.calis.edu.cn/huiyiziliao/huiyi21/shjtdx/cygj/info-6638.shtml
5.七vertical七、vertical-align属性、透明度属性及兼容、ps常用工具、常见的图片格式、项目规范、命名参考、iconfont的使用,此文转载自:https://blog.csdn.net/qq_52426181/article/details/110228561一、css其他属性1、vertical-align属性设置元素的垂直对齐方式,适用于行级元素、https://blog.51cto.com/phyger/5276254
6.如何快速截图?常用截图工具快捷键大全电脑知识学会使用小白系统工具,让您的生活多一份收入,赚钱机会就在眼前! 简介: 截图是我们在电脑和手机上经常会用到的功能,无论是在工作中还是生活中,都能给我们提供很大的便利。本文将为大家介绍几种常用的截图工具以及它们的快捷键,帮助大家提高效率,更快捷地截取所需的图片。 https://www.163987.com/jiaocheng/138103.html
7.常用的UI设计工具大全!本文为大家整理了这份常用的 UI 设计工具大全,常用的 UI 设计工具通常可以分为矢量绘图工具、原型工具以及图片编辑工具。矢量绘图工具方面,AdobeIllustrator和Sketch都是优秀的选择。这两款 UI 设计工具提供强大的矢量绘图功能,能轻松绘制各种图标、按钮等界面元素。如果想要尝试 AI 生成图像,国内的 UI 设计工具即时 AI...https://js.design/special/article/commonly-used-ui-design-tools.html
8.EXCEL集成工具箱详细教程常用工具 【繁简转换】 可视化的繁简体GB与BGK码以及GB2与BIG5码相互转换,可以复制文本到当前窗体中文本进行转换,也可以实现单个文件或批量文件的转换。在窗体中双击文本字符串尾即可实现自动选定文本并自动复制功能。本工具较同类转换工具准确率达100%。 【背景颜色】 提供可视化的可选择着色方式的背景着色功能,默认启用...https://www.yjbys.com/edu/office/460212.html
9.生活中常用工具简笔画简笔画图片大全生活中常用工具简笔画劳动工具简笔画彩色 生活用品怎么画简单常见生活用品简笔画大全 生活用品怎么画简单常见生活用品简笔画大全 劳动工具简笔画图片 铁锹的简单画法工具类简笔画生活物品简笔画简笔画大全 扳手简笔画法工具类 电烤枪简笔画 工具类简笔画 螺丝刀简笔画图片教程 活扳手的简笔画法工具类 工具简...https://www.puchedu.cn/jianbihua/e92b58b4e75a9ff7.html
10.在线图片链接生成器app常用工具推荐在线图片链接生成器app是一种可以将图片上传到互联网上,并生成一个可以在其他网站或平台上分享的图片地址的应用程序。在线图片链接生成器app有很多种,有些是免费的,有些是收费的,有些需要注册账号,有些不需要。在线图片链接生成器app的优点是可以节省本地存储空间,方便快捷地分享图片,提高图片的可见性和传播性。在线...http://app.applebyme.cn/cloud/appshangjia/3167.html
11.产品经理干货新公布的7种互联网产品经理常用工具,这些细节你不得...摘要众所周知,产品经理的工作职责就是帮助企业做产品管理,并根据市场和用户的需求,确定开发某种产品,可见产品经理对于一个企业的重要性,现如今,越来越多的人都看中了产品经理的重要性,考虑到大家的发展,所以今天就单独讲讲互联网产品经理常用工具。 一、互联网产品经理常用工具——原型设计工具 ...https://m.hqwx.com/news/2020-3/15845851578421.html
12.吐血推荐20个高效实用的网站Android模块下有常用网站、经典博客、开发服务、推送服务、通信服务、源码下载等。ios模块下有常用网站、经典博客、源码下载等。工具模块下有常用工具、安卓工具、前端工具、设计工具、测试工具等。后端模块下有 JAVA、 PHP、Python。设计高清图库、素材下载、配色方案、界面设计、字体设计。https://www.douban.com/note/749292560/