关于内存的小结

关于内存:
一:OOM原因分析
项目OOM设备信息截图:
在这里插入图片描述
8.0系统以下发生OOM的频率较高。
Bitmap图片是造成OOM的主要原因。
应用程序的内存分配和垃圾回收都是由Android虚拟机完成的,在Android 5.0以下,使用的是Dalvik虚拟机,5.0及以上,则使用的是ART虚拟机。
系统变更Bitmap在内存中分配位置的变化:
1.Android 3.0之前是存放在Java堆内存中,像素数据存储在Native heap中,如果不手动调用 recycle,Bitmap Native 内存的回收完全依赖 finalize 函数回调,熟悉 Java 的同学应该知道,这个时机不太可控。
2.Android 3.0~Android 7.0 将 Bitmap 对象和像素数据统一放到 Java 堆中,这样就算我们不调用 recycle,Bitmap 内存也会随着对象一起被回收。不过 Bitmap 是内存消耗的大户,把它的内存放到 Java 堆中似乎不是那么美妙。即使是最新的华为 Mate 20,最大的 Java 堆限制也才到 512MB,可能我的物理内存还有 5GB,但是应用还是会因为 Java 堆内存不足导致 OOM。Bitmap 放到 Java 堆的另外一个问题会引起大量的 GC,对系统内存也没有完全利用起来。
Android 内存模型:
在这里插入图片描述

其中堆空间完全由程序员控制:
RAM的一部分被操作系统留作他用,比如显存等等,当然这个程序员无法干预,我们也不必过多地关注它
我们使用的C malloc、C++ new和java new所申请的空间都是heap空间。
C/C++申请的内存空间在native heap中,
而java申请的内存空间则在dalvik heap中。
所以:
java程序发生OMM并不是表示RAM(物理内存)不足。而是堆内存超出了dalvik.vm.heapsize的限制。
—当RAM内存不够是会如何?
这时Android的memory killer会起作用,当RAM所剩不多时,memory killer会杀死一些优先级比较低的进程来释放物理内存,让高优先级程序得到更多的内存。
low memory killer优先级排队等着被KiIl:
在这里插入图片描述

Android 3.0~Android 7.0 将Bitmap存储到Native内存中:

// 步骤一:申请一张空的 Native Bitmap
Bitmap nativeBitmap = nativeCreateBitmap(dstWidth, dstHeight, nativeConfig, 22);

// 步骤二:申请一张普通的 Java Bitmap
Bitmap srcBitmap = BitmapFactory.decodeResource(res, id);

// 步骤三:使用 Java Bitmap 将内容绘制到 Native Bitmap 中
mNativeCanvas.setBitmap(nativeBitmap);
mNativeCanvas.drawBitmap(srcBitmap, mSrcRect, mDstRect, mPaint);

// 步骤四:释放 Java Bitmap 内存
srcBitmap.recycle();
srcBitmap = null;
二:对图片的处理:
1.常见的操作:inPreferredConfig的默认参数是Bitmap.Config.ARGB_8888(Bitmap.Config.ARGB_4444已经被系统弃用),即:就是由4个8位组成即32位,RGB_565就是R为5位,G为6位,B为5位共16位,内存占用上会少一半;
2.质量压缩:
常见的压缩框架Luban 、Compressor;
在实际使用过程中,我们通常会结合三种压缩方式使用,一般使用的步骤如下,
使用邻近采样对原始的图片进行采样,将图片控制到比目标尺寸稍大的大小,防止 OOM;
使用双线性采样对图片的尺寸进行压缩,控制图片的尺寸为目标的大小;
对上述两个步骤之后得到的图片 Bitmap 进行质量压缩,并将其输出到磁盘上。
参考: https://mp.weixin.qq.com/s/KgUbnQpgTmJjmO1ibQm5SA;
三:JAVA内存和Android内存
1.JVM 将整个内存划分为了几块,分别如下所示:
1)、方法区:存储类信息、常量、静态变量等。=> 所有线程共享
2)、虚拟机栈:存储局部变量表、操作数栈等。
3)、本地方法栈:不同与虚拟机栈为 Java 方法服务、它是为 Native 方法服务的。
4)、堆:内存最大的区域,每一个对象实际分配内存都是在堆上进行分配的,,而在虚拟机栈中分配的只是引用,这些引用会指向堆中真正存储的对象。此外,堆也是垃圾回收器(GC)所主要作用的区域,并且,内存泄漏也都是发生在这个区域。=> 所有线程共享
5)、程序计数器:存储当前线程执行目标方法执行到了第几行。
2.Android 内存回收机制:
Generational详情以及OOM场景和处理方式、MAT内存泄漏分析场景参考:https://juejin.im/post/5e72b2d151882549236f9cb8
和JVM类似也有Generational Heap Memory模型:
Young Generation(年轻代)
Old Generation(年老代)
Permanent Generation(持久代)
GC方式也和JVM中差不多,主要的有标记、标记整理、指针、分代算法,但每个Generational区域采用的方式有区别;
Dalvik 与 ART 区别:
Dalivk 仅固定一种回收算法。
ART 回收算法可运行期选择。
ART 具备内存整理能力,减少内存空洞。
内存泄漏:
GC会选择一些还存活的对象作为内存遍历的根节点GC Roots,通过对GC Roots的可达性来判断是否需要回收,JVM中可达性算法,类似一条关系链,这条链上 的对象依赖关系,每一个对象都不被持有引用才能回收,即都不可达。泄漏情况是不被使用的不可达对象回收时被可达对象持有引用导致GC失败;
内存抖动:
频繁的GC导致,可能会引起OOM,因为频繁的创建对象导致很多的内存碎片或者内存不足,不连续的内存无法被分配。缓存的方式可以避免,避免频繁的创建对象的操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值