1.确定频繁分配内存的代码路径。
DDMS下的Allocation Tracker。它可以显示出程序运行中频繁分配内存的部分,并准确定位到对应的代码。
2.减少频繁的内存分配。
减少频繁地创建对象或者不在这些地方创建对象是一个显而易见的方法。
也有一些比较隐秘的内存消耗点,下面就介绍一下for循环的内存消耗。
InputStream is =this.getResources().openRawResource(R.drawable.img);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 10; //width,hight设为原来的十分一
Bitmap bm =BitmapFactory.decodeStream(is,null,options);//BitmapFactory.decodeStream方法,
创建出一个bitmap,再将其设为ImageView的 source,decodeStream最大的秘密在于其直接用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap从而节省了java层的空间(避免了一些对象的创建)。如果在读取时加上图片的Config参数,可以更有效减少加载的内存,从而减少发生OOM发生的几率。
if(!bm.isRecycle() ){
bm.recycle() //回收图片所占的内存
system.gc() //提醒系统及时回收
}
调用recycle(),会开启一个线程去处理,具体什么时候回收只有系统知道。(属于建议 JVM 进行垃圾回收)
这个就是为什么我们有的地方调用了它,那个地方还是会报oom的原因。
但是有总归比没有好,它可以有效减少oom的概率。
回收缓存资源
(1)//用来存放图片的缓存
HashMap<Integer, Bitmap>bitmapCache = new HashMap<Integer, Bitmap>();
//如果没有图片,或者不存在
if(bitmapCache.isEmpty() || !AppConst.bitmapCache.containsKey(position)){
bitmapCache.put(position,bm);
}
(2)定义FreeBitmap函数,在activity结束的时候,调用FreeBitmap函数,回收map中的资源
private void FreeBitmap(HashMap<Integer, Bitmap> cache){
if(cache.isEmpty()){
return;
}
for(Bitmap bitmap:cache.values()){
if(bitmap != null && !bitmap.isRecycled()){
bitmap.recycle();
}
}
cache.clear();
}
(1)增强程序堆内存的处理效率:
开发一些大型游戏或耗资源的应用时可考虑手动干涉GC处理,如程序onCreate时调用VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
(2)强行设置APP最小内存大小:
VMRuntime.getRuntime().setMinimumHeapSize(6* 1024* 1024); //设置最小heap内存为6MB大小
工作中遇到了一个需要debug的应用,需要去try修改dalvik.vm.heapgrowthlimit来check这个问题。所以,这里记录下,修改的方法:
1. dalvik.vm.heapgrowthlimit的设置在 /system/build.prop中
2. adb remount / adb pull /system/build.prop
3. 修改build.prop文件,将dalvik.vm.heapgrowthlimit修改后,adb pull /system/
4. chmod修改build.prop的权限。这里要注意,我开始修改的是chmod 777,后来系统起不来。ll 查看system/下文件权限,发现时744。同理: chmod 744,发现就 OK了。原来权限给高了还不行。
假设你有一个HashMap对象,你可以将它声明为HashMap或者Map:
Map map1 = new HashMap();
HashMap map2 = new HashMap();
哪个更好呢?
按照传统的观点Map会更好些,因为这样你可以改变他的具体实现类,只要这个类继承自Map接口。传统的观点对于传统的程序是正确的,但是它并不适合嵌入式系统。调用一个接口的引用会比调用实体类的引用多花费一倍的时间。如果HashMap完全适合你的程序,那么使用Map就没有什么价值。如果有些地方你不能确定,先避免使用Map,剩下的交给IDE提供的重构功能好了。(当然公共API是一个例外:一个好的API常常会牺牲一些性能)
枚举变量非常方便,但不幸的是它会牺牲执行的速度和并大幅增加文件体积。例如:
public class Foo {
public enum Shrubbery { GROUND, CRAWLING, HANGING }
}
会产生一个900字节的.class文件(Foo Shubbery.class)。在它被首次调用时,这个类会调用初始化方法来准备每个枚举变量。每个枚举项都会被声明成一个静态变量,并被赋值。然后将这些静态变量放在一个名为” VALUES”的静态数组变量中。而这么一大堆代码,仅仅是为了使用三个 整数。
这样:Shrubbery shrub =Shrubbery.GROUND;会引起一个对静态变量的引用,如果这个静态变量是final int,那么编译器会直接内联这个常数。一方面说,使用枚举变量可以让你的API更出色,并能提供编译时的检查。所以在通常的时候你毫无疑问应该为公共API选择枚举变量。但是当性能方面有所限制的时候,你就应该避免这种做法了。