使用largeHeap为app增加可使用内存

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hzypf/article/details/60633666

  在平时的开发中,难免会遇到OOM,特别是处理Bitmap对象的时候,造成OOM的原因,一般有代码设计不合理,内存泄漏,内存不能得到释放,也有可能是系统为你的App分配的内存实在太小。
  在最近的项目中,需要一个拍照功能,调用系统相机拍照,并对照片进行了方向调整(手机Camera的图像数据都是来自于摄像头硬件的图像传感器(Image Sensor),这个Sensor被固定到手机之后是有一个默认的取景方向的,即拍照后的照片如果竖屏展示,可能不是正的,具体手机的偏转方向有所差别),添加水印(手机当前的gps信息和时间),进行压缩,最后以缩略图展示。由于没有使用别人封装好的第三方库,实现起来耗费了一些时间,最后测试阶段,发现大多数手机都已经正常工作,唯独自己的一只三星的S5,一直会OOM,利用Android studio 的Monitor一看,内存跑到100MB程序就挂了,于是我就是用了largeHeap为虚拟机扩大了可用内存。
  基础概念铺垫:
  虚拟机的运行时内存一般由堆和栈两大部分构成。
  栈是存储方法调用的一片内存数据区。
  堆内存占据了虚拟机的大部分内存空间,程序执行时产生的对象就分配在堆内存上。
  如果是堆内存没有可用的空间存储生成的对象,JVM会抛出java.lang.OutOfMemoryError
  

largeHeap如何使用:

 <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

在AndroidManifest.xml中的application节点添加一句android:largeHeap=“true” 即可。

largeHeap能增加多大内存

我们可以通过以下两个方法查看我们内存的大小
ActivityManager.getMemoryClass()获得内用正常情况下内存的大小
ActivityManager.getLargeMemoryClass()可以获得开启largeHeap最大的内存大小
在Android系统中,在 /system/build.prop ,存放着关于dvm分配内存大小的配置信息,如下。

dalvik.vm.heapstartsize=8m
dalvik.vm.heapgrowthlimit=128m
dalvik.vm.heapsize=512m
dalvik.vm.heaptargetutilization=0.75
dalvik.vm.heapminfree=2m
dalvik.vm.heapmaxfree=8m

dalvik.vm.heapstartsize=8m

相当于虚拟机的 -Xms配置,该项用来设置堆内存的初始大小。

dalvik.vm.heapgrowthlimit=128m

相当于虚拟机的 -XX:HeapGrowthLimit配置,该项用来设置一个标准的应用的最大堆内存大小。一个标准的应用就是没有使用android:largeHeap的应用。

其中dalvik.vm.heapsize=512m

相当于虚拟机的 -Xmx配置,该项设置了使用android:largeHeap的应用的最大堆内存大小。

检验效果:
在代码中使用
Log.e("memory:",Runtime.getRuntime().maxMemory()+"");//输出最大可用内存
Log.e("memory:",Runtime.getRuntime().freeMemory()+"");//输出当前可用内存

这里写图片描述
这是正常情况下的最大可用内存。
这里写图片描述
使用largeheap后明显能够看到使用的内存大于了没设置过的128mb。
这里对可用内存进行一个说明:当初始化的可用内存不能满足需求时,系统自动将可用内存扩充,所以看到这里可用内存只有9MB的童鞋不需要担心,但最大不得超过最大可用内存

补充说明:设置largeHeap是不需要权限的,系统GC回收从2.3开始引入并发的方式,所以使用largeHeap是从4.0开始支持,对系统GC影响微乎其微,其实使用largeHeap是指标不治本的,最主要的还是应该通过代码上去查找问题解决问题。

展开阅读全文

读取文件造成内存使用增加

03-04

我在一个开发板上, os是linux.rn然后mount U盘,rn代码如下。rn[code=c]rn/*rn U盘是挂接在/mnt/usb文件夹下。rn U盘里面有file0.bin , file1.bin, file2.bin, file3.bin, file4.bin 每个文件大小都是1GB.rn*/rnvoid *thread_usbtest(void *argc)rnrn int nfd, nsize;rn unsigned int nIndex;rn unsigned char szBuf[204*100];rn rn nfd = -1;rn nIndex = 0;rn while(1)rn rn // 打开文件- 循环读取rn if(nfd < 0)rn nfd = open("/mnt/usb/file%d.bin", nIndex%5);rn if(nfd < 0)rn rn sleep(1); // 等待1秒。rn continue;rn rn rn // 读取文件。rn nSize = read(nfd, szBuf, sizeof(szBuf) / 188 * 188);rn if(nSize <= 0) // 出错,或者读取完了。rn rn close(nfd);rn nfd = -1;rn rn rnrnrnint main()rnrn int nRet;rn pthread_t thusb;rnrn // 开启线程rn nRet = pthread_create(&thusb, NULL, thread_usbtest, NULL);rn rn while(1)rn sleep(60);rnrn[/code]rn然后编译, 输出文件为device.elfrn然后我在shell 中在后台运行程序: device.elf &rn然后在shell中用free命令查看内存使用。发现内存使用在一直增加, 直到快用完了。输出如下。我的内存大小为384MB.rn total used free shared buffers rnmem 383684 363932 19752 0 2460rn-/+buffers 361472 22212 rnswap 0 0 0rnrn文件系统是基于busybox.rn不知道为什么内存一直增加?内存谁使用了那么多?rn后面我用kill命令把这个程序直接kill掉。再用free命令,发现内存使用与前面相差不大。rn如果这个时候我用umount /mnt/usb 卸载掉U盘, 这个时候再用free, 发现mem 的used为40123, 变得很小了。 论坛

Socket会使内存使用增加(溢出)?

04-21

我的代码中使用EVC文档中例子程序,其中debug()方法是使用GlobalsMemoryStatus()获得系统剩余内存的,经过多次测试,在debug(TEXT("2"))~debug(TEXT("3")),debug(TEXT("6"))~debug(TEXT("7")),rn内存会减少,而且这段代码结束后(debug(TEXT("9")))减少的内存仍然没有完全被释放(一部分被释放了),怎么回事呢?rn我的代码中需要很大量次数的进行间断性Socket通讯,这样内存一直在减少的话,我测试中内存已经超过98%了。rn如下:rnSOCKET ServerSock = INVALID_SOCKET; rnSOCKADDR_IN destination_sin; rnPHOSTENT phostent = NULL; rnrnWSADATA WSAData; rnrn rndebug(TEXT("1"));rnrnif (WSAStartup (MAKEWORD(1,1), &WSAData) != 0) rnrn return FALSE;rnrndebug(TEXT("2"));rn rnrnif ((ServerSock = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)rnrn return FALSE;rnrndebug(TEXT("3"));rn rndestination_sin.sin_family = AF_INET;rndestination_sin.sin_addr.s_addr=inet_addr(HOSTIP);rndestination_sin.sin_port = htons (6667); rn rnif (connect (ServerSock, (PSOCKADDR) &destination_sin, sizeof (destination_sin)) == SOCKET_ERROR) rnrn rn closesocket (ServerSock);rn return FALSE;rnrndebug(TEXT("4"));rn rnrnif (send (ServerSock, "To Server.", strlen ("To Server.") + 1, 0)== SOCKET_ERROR) rnrn rnrndebug(TEXT("5"));rn rnrnshutdown (ServerSock, 0x01);rndebug(TEXT("6"));rn rnrniReturn = recv (ServerSock, szClientA, sizeof (szClientA), 0);rn rnif (iReturn == SOCKET_ERROR)rnrnrnrnelse if (iReturn == 0)rnrnrnrnelsernrnrnrnrndebug(TEXT("7"));rn rnshutdown (ServerSock, 0x00);rndebug(TEXT("8"));rn rnclosesocket (ServerSock);rn rn rnWSACleanup ();rndebug(TEXT("9")); 论坛

没有更多推荐了,返回首页