Android性能优化一 内存优化

353 阅读4分钟

在Android 使用的是davilk虚拟机 它和java虚拟机 类似 但是它是使用基于寄存器的 java基于栈的
davilk虚拟机的 编译出来的文件也不同 它是拥有 一个dex文件有多个class 而java虚拟机是 一个文件对应一个class

davilk虚拟机 是先编译成class 文件 然后通过 dx 工具在打包成一个dex文件。

一个android app 就是一个davilk虚拟机 它是由zygote进程中davilk虚拟机 复制过来的。

adb shell cat /system/build.prop 查看系统设置最大 java object heap 的大小

在Android启动中 davilk虚拟机 java object heap size navtive heap size
java object heap 是有限制的 可以通过 root adb shell cat /system/build.prop 来查看 navtive heap size 大概率是没有限制

adb shell cat /proc/pid/oom_adj 查看当前app所处于的进程

android 的 前台进程 0 可见进程 后台进程 11 服务5 服务8 空进程 -11--16

如果两个进程都是后台进程 11 那么 谁占用的内存大就回收谁。 所以内存回收非常重要

如何 查看 adb shell cat /proc/pid/oom_adj

OOM问题:

内存泄漏: 当应用周期内 不再使用的对象被GC ROOTS引用 导致不能回收 会使实际可用的java 堆内存变小 就会发生内存泄漏

内存泄漏 超过单个应用最大的使用内存,超出这个值就会OOM

OOM 有很多中 不一定是 超过最大使用堆内存

OOM

1. JAVA堆内存溢出
2. 无足够的连续空间
3. FD数量超过限制
4. 线程数量超过限制 
5. 虚拟内存不足

我们可以使用 adb shell dumpsys meminfo --package 包名

如果多个设备 adb -s xxx shell

从下载hprof后 要通过Android sdk 中platm-tools hprof-conv.exe 来转换成MAT所需要的文件

out-coming 是 该对象中引用了谁 in-comeing 是 谁引用了该对象

  1. 资源性的泄漏 比如database中
  2. 注册对象未注销 比如 广播 eventBus
  3. 类的静态变量持有大数据对象。
  4. 单例模式造成的泄漏 比如Context 传入了Activity
  5. 非静态内部类的静态实例
  6. Handler的零时性泄漏
  7. 容器中的对象没有clear 并且设置null
  8. webView 需要使用aidl进程通信

地图中 BitMapFactory.Option 参数 中有个参数 inJustDecodeBounds=true 可以不加载图片不分配内存,但会返回图片的宽度和高度。 然后 通过samleSize来缩放图片比例

1个像素 有一个参数Config ALPHA(1) 是占1个字节(byte) RGB_565是占2个字节(byte)
ARGB_888是占4个字节 ARGB_F16占 8个字节(byte) 、

在Android图片中占用的内存大小是
那么大小就是

1920x1080像素 占多少内存 1920x1080x4x((设备密度/图片所在文件夹的密度)^2)/1024= KB

mdpi hdpi xdpi xxdpi xxxdpi 160 240 320 480 560

但是在文件和网络上加载的图片就没有1920x1080x4/1024=kb

8bit(位)=1Byte(字节) 

1024Byte(字节)=1KB 

1024KB=1MB 

1024MB=1GB 

1024GB=1TB

Bitmap的内存模型 Android 3.0-4.4 bitMap对象保存在java Heap 像素数据保存在 native Heap Android 5.0-7.0 bitmap对象保存在java Heap 像素数据保证在 java Heap Android 8.0 bimap对象保存在java Heap 像素数据保存在 native Heap

内存优化整体思想:

  1. 设备分级:
  2. BitMap优化 统一图片库 线上 线下监控
  3. glide图片加载库

LeakCanary 内存检测工具
两部分 1.找出泄漏的嫌疑的对象。原理 2.确诊:haha开源库 利用这个可达性分析

LeakCanary的原理 在ActivityThread中的bindAppcalition方法 ContentProvider.onCreate 会比Appcaliton.onCreate 更早执行

LeakCanary检测Activity退出的原理
ActivityLifecycleCallbacks 可以监听Activity的生命周期  Fragment的生命周期
JAVA四种引用和引用队列ReferenceQueue的关系

RefereQueue 引用队列 就是存放引用的队列

作用:当作用于Reference对象所引用的对象被GC回收的时候,该Reference对象将会被加入引用队列的末尾

当弱引用 WeakReference weakReference=new WeakReference(obj,referenceQueue)

leakcanary watch 一个对象5s 加入观察列表