众所周知,在写 android 程序的时候,很容易出现 OOM ,而出现的时机大多数是由 Bitmap decode 引发的:

1

ERROR/AndroidRuntime(16350): java.lang.OutOfMemoryError: bitmap size exceeds VM budget

我们知道,android程序内存一般限制在16M,当然也有24M的,而android程序内存被分为2部分:native和dalvik:

dalvik就是我们平常说的java堆,我们创建的对象是在这里面分配的,而bitmap是直接在native上分配的,对于内存的限制是 native+dalvik 不能超过最大限制。

注:一旦内存分配给Java后,以后这块内存纵然开释后,也只能给Java的施用,这个估计跟java虚拟机里把内存分成好几块进行缓存的原因有关,反正C就别想用到这块的内存了,所以要是Java突然占用了一个大块内存,纵然很快开释了:
C能施用的内存 = 16M - Java某一瞬间占用的最大内存。
  而Bitmap的生成是通过malloc进行内存分配的,占用的是C的内存,这个也就说明了,上面所说的的4MBitmap无法生成的原因,因为在13MJava用过后,剩下C能用的只有3M了。

用以下命令可以查看程序的内存使用情况:

adb shell dumpsys meminfo packagenameor pid 程序的包名或者进程id

其中size是需要的内存,而allocated是分配了的内存,对应的2列分别是native和dalvik,当总数也就是total这一列超过单个程序内存的最大限制时,OOM就很有可能会出现了。

多数时候,发生OOM 都是在做一些跟图片相关的操作,以下提出一些建议尽量可以减少这种情况的发生:

1

.decode bitmap 的时候,尽量配置下Options,例如:inSameSize

2

.Bitmap使用完以后,调用 bitmap.recycle()来释放内存

3

.如果应用是基于图片的应用,尽量采用LazyLoad和DymanicRecycle

4.decode bitmap 的时候,将decode代码trycatch出来,catchoom error,避免程序crash,可以在catch里面做一些释放内存操作

关于Android的Native内存和Dalvik内存

1.Dalvik内存

每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。

很多人认为Dalvik虚拟机是一个Java虚拟机,因为Android的编程语言恰恰就是Java语言。但是这种说法并不准确,因为 Dalvik虚拟机并不是按照Java虚拟机的规范来实现的,两者并不兼容;

同时还要两个明显的不同:
1.Java虚拟机运行的是Java字节码,而Dalvik虚拟机运行的则是其专有的文件格式DEX(Dalvik Executable)。

2.在Java SE程序中的Java类会被编译成一个或者多个字节码文件(.class)然后打包到JAR文件,而后Java虚拟机会从相应的CLASS文件和JAR文件中获取相应的字节码;Android应用虽然也是使用Java语言进行编程,但是在编译成CLASS文件后,还会通过一个工具(dx)将应用所有的 CLASS文件转换成一个DEX文件,而后Dalvik虚拟机会从其中读取指令和数据。

Dalvik虚拟机的简介:

Dalvik虚拟机主要是完成对象生命周期的管理,堆栈的管理,线程管理,安全和异常的管理,以及垃圾回收等等重要功能。
Dalvik
虚拟机的主要特征Dalvik 虚拟机非常适合在移动终端上使用,相对于在桌面系统和服务器系统运行的虚拟机而言,它不需要很快的CPU速度和大量的内存空间。

Dalvik虚拟机有如下几个主要特征:

1.专有的DEX文件格式

DEXDalvik虚拟机专用的文件格式,而问什么弃用已有的字节码文件(CLASS文件)而采用新的格式呢?一个应用中会定义很多类,编译完成后即会有很多相应的CLASS文件,CLASS文件间会有不少冗余的信息;而DEX文件格式会把所有的 CLASS文件内容整合到一个文件中。这样,除了减少整体的文件尺寸,I/O操作,也提高了类的查找速度。

2.增加了新的操作码的支

3.文件结构尽量简洁,使用等长的指令,借以提高解析速度
4.
尽量扩大只读结构的大小,借以提高跨进程的数据共享

2.Native内存

如何修改Android应用程序的默认最大内存值

Android应用程序的默认最大内存值为16M,有些应用程序可能会出现内存溢出,譬如ERROR/AndroidRuntime(264):java.lang.OutOfMemoryError: bitmap size exceeds VM budget

除了要检查修正代码之外,还可以考虑修改Android应用程序的默认最大内存值。

修改应用程序的默认最大内存有2种方法:

1、修改代码,适用于自己编译烧机:

当应用程序分配内存时,会调用到dalvik/vm/alloc/HeapSource.c中的dvmTrackExternalAllocation()方法,继而调用到externalAllocPossible()方法,该方法要求当前堆已使用的大小(由currentHeapSize和hs->externalBytesAllocated构成)加上我们需要再次分配的内存大小不能超过堆的最大内存值,如果超过就会报错。
有两个地方决定了一个堆的最大内存:
1)dalvik/vm/Init.c中的
gDvm.heapSizeMax = 16 * 1024 * 1024; // Spec says 75%physical mem
2)frameworks/base/core/jni/AndroidRuntime.cpp中的
property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4,"16m");
因此解决办法就是将以上2点中默认的16M改大一点,譬如32M。

2、修改配置文件,适用于烧机后的版本。

修改或添加/system/build.prop中的配置项:

dalvik.vm.heapstartsize=20m

dalvik.vm.heapgrowthlimit=200m

dalvik.vm.heapsize=320m

更多相关文章

  1. android apkbuilder.bat批处理
  2. Android中MVP模式的内存泄漏解决及Retrofit2、RxJava中断网络请
  3. Android(安卓)SDK三种更新失败及其解决方法
  4. android 导出带数据库文件的APK
  5. Android之Gradle基础
  6. could not write file\android-7\/system.img, No space left
  7. Android之使用Http协议实现文件上传功能
  8. android aidl调用进程间服务的方法
  9. Android(安卓)colors.xml 颜色配置文件

随机推荐

  1. Android自定义视图三:给自定义视图添加“
  2. Android(安卓)Layout布局文件里的android
  3. 评论:Android其实不免费
  4. Android反编译工具jadx的使用
  5. 安卓的发展历程
  6. 关于获取Android中的文件内容
  7. android window类
  8. 推荐Android两种屏幕适配方案
  9. 10个经典的Android开源应用项目
  10. Android中的网络时间同步