Android:库中内存不足异常
我的应用程序显示了9个类别的列表,每个类别都显示了一个基于图库的coverflow(由Neil Davies慷慨提供),其中包含所选类别的图像 这些图像是从网络上获取的,每个图像的大小从300K到500K不等,并存储在一个可绘制的数组列表中。此数据使用BaseAdapter绑定到coverflow(代码如下)。Android:库中内存不足异常,android,memory-leaks,gallery,Android,Memory Leaks,Gallery,我的应用程序显示了9个类别的列表,每个类别都显示了一个基于图库的coverflow(由Neil Davies慷慨提供),其中包含所选类别的图像 这些图像是从网络上获取的,每个图像的大小从300K到500K不等,并存储在一个可绘制的数组列表中。此数据使用BaseAdapter绑定到coverflow(代码如下)。 每次我退出coverflow并返回类别列表时,我都会清除arrayList(同样,下面的代码) 在场景1中,我的arrayList包含5个可提取项。在这个场景中,我可以自由浏览所有类别并
每次我退出coverflow并返回类别列表时,我都会清除arrayList(同样,下面的代码) 在场景1中,我的arrayList包含5个可提取项。在这个场景中,我可以自由浏览所有类别并显示它们的图像。在我的测试中,我在所有类别中循环了5次,这似乎足以确定没有问题 在场景2中,我的arrayList包含10个可提取项。在这种情况下,我在浏览第5或第6类中的图像时会出现OutOfMemoryError异常: 07-13 08:38:21.266: ERROR/dalvikvm-heap(2133): 819840-byte external allocation too large for this process. 07-13 08:38:21.266: ERROR/(2133): VM won't let us allocate 819840 bytes 07-13 08:38:21.277: DEBUG/skia(2133): --- decoder->decode returned false 07-13 08:38:21.287: WARN/dalvikvm(2133): threadid=25: thread exiting with uncaught exception (group=0x4001b188) 07-13 08:38:21.296: ERROR/AndroidRuntime(2133): Uncaught handler: thread Thread-64 exiting due to uncaught exception 07-13 08:38:21.308: ERROR/AndroidRuntime(2133): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 07-13 08:38:21.308: ERROR/AndroidRuntime(2133): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 07-13 08:38:21.308: ERROR/AndroidRuntime(2133): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:459) 07-13 08:38:21.308: ERROR/AndroidRuntime(2133): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:323) 07-13 08:38:21.308: ERROR/AndroidRuntime(2133): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697) 07-13 08:38:21.308: ERROR/AndroidRuntime(2133): at android.graphics.drawable.Drawable.createFromStream(Drawable.java:657) 在输入类别时填充数据源:
for (int i = 0; i < ImageBuffer.getInstance().getImageArraySize(); i++)
{
String imageUrl = ImageBuffer.getInstance().getImageUrl(i);
Log.v("Initial", imageUrl);
Drawable fullImage = AsyncImageLoader.getInstance().loadImageByUrl(imageUrl);
ImageBuffer.getInstance().getImages().add(i, fullImage);
}
for(int i=0;i
退出类别时清除数据源(在finish()中):
for(int i=0;i
编辑:
好的,我在coverflow上应用了Mathias的LogHeap函数,下面是一些输出。
在加载第一个库之前:
DEBUG/Application(5221): debug. =================================
DEBUG/Application(5221): debug.heap native: allocated 6.20MB of 6.28MB (0.07MB free) in [com.example.Coverflow]
DEBUG/Application(5221): debug.memory: allocated: 4.00MB of 24.00MB (0.00MB free)
DEBUG/dalvikvm(5221): GC freed 4558 objects / 638152 bytes in 84ms
DEBUG/dalvikvm(5221): GC freed 17 objects / 808 bytes in 67ms
DEBUG/Application(5221): debug. =================================
DEBUG/Application(5221): debug.heap native: allocated 14.83MB of 16.89MB (0.11MB free) in [com.example.Coverflow]
DEBUG/Application(5221): debug.memory: allocated: 4.00MB of 24.00MB (1.00MB free)
DEBUG/dalvikvm(5221): GC freed 330 objects / 17920 bytes in 77ms
DEBUG/dalvikvm(5221): GC freed 13 objects / 760 bytes in 67ms
调试/应用程序(5221):调试=================================
调试/应用程序(5221):DEBUG.heap native:在[com.example.Coverflow]中分配了6.20MB的6.28MB(0.07MB空闲空间)
调试/应用程序(5221):调试。内存:已分配:24.00MB中的4.00MB(0.00MB可用)
DEBUG/dalvikvm(5221):GC在84ms内释放4558个对象/638152字节
DEBUG/dalvikvm(5221):GC在67ms内释放了17个对象/808字节
进入第一个画廊后:
DEBUG/Application(5221): debug. =================================
DEBUG/Application(5221): debug.heap native: allocated 14.90MB of 16.89MB (0.07MB free) in [com.example.Coverflow]
DEBUG/Application(5221): debug.memory: allocated: 4.00MB of 24.00MB (1.00MB free)
DEBUG/dalvikvm(5221): GC freed 357 objects / 50080 bytes in 68ms
DEBUG/dalvikvm(5221): GC freed 353 objects / 27312 bytes in 67ms
调试/应用程序(5221):调试=================================
调试/应用程序(5221):DEBUG.heap native:在[com.example.Coverflow]中分配了14.90MB的16.89MB(0.07MB空闲空间)
调试/应用程序(5221):调试。内存:已分配:24.00MB中的4.00MB(1.00MB可用)
DEBUG/dalvikvm(5221):GC在68ms内释放了357个对象/50080字节
DEBUG/dalvikvm(5221):GC在67毫秒内释放了353个对象/27312字节
在现有第一个库之后:
DEBUG/Application(5221): debug. =================================
DEBUG/Application(5221): debug.heap native: allocated 6.20MB of 6.28MB (0.07MB free) in [com.example.Coverflow]
DEBUG/Application(5221): debug.memory: allocated: 4.00MB of 24.00MB (0.00MB free)
DEBUG/dalvikvm(5221): GC freed 4558 objects / 638152 bytes in 84ms
DEBUG/dalvikvm(5221): GC freed 17 objects / 808 bytes in 67ms
DEBUG/Application(5221): debug. =================================
DEBUG/Application(5221): debug.heap native: allocated 14.83MB of 16.89MB (0.11MB free) in [com.example.Coverflow]
DEBUG/Application(5221): debug.memory: allocated: 4.00MB of 24.00MB (1.00MB free)
DEBUG/dalvikvm(5221): GC freed 330 objects / 17920 bytes in 77ms
DEBUG/dalvikvm(5221): GC freed 13 objects / 760 bytes in 67ms
调试/应用程序(5221):调试=================================
DEBUG/Application(5221):DEBUG.heap native:在[com.example.Coverflow]中分配了14.83MB的16.89MB(0.11MB空闲空间)
调试/应用程序(5221):调试。内存:已分配:24.00MB中的4.00MB(1.00MB可用)
DEBUG/dalvikvm(5221):GC在77ms内释放330个对象/17920字节
DEBUG/dalvikvm(5221):GC在67毫秒内释放了13个对象/760字节
进入第五画廊后:
DEBUG/Application(5221): debug. =================================
DEBUG/Application(5221): debug.heap native: allocated 16.80MB of 23.32MB (0.08MB free) in [com.example.Coverflow]
DEBUG/Application(5221): debug.memory: allocated: 4.00MB of 24.00MB (1.00MB free)
DEBUG/dalvikvm(5221): GC freed 842 objects / 99256 bytes in 73ms
DEBUG/dalvikvm(5221): GC freed 306 objects / 24896 bytes in 69ms
DEBUG/Application(5221): debug. =================================
DEBUG/Application(5221): debug.heap native: allocated 16.74MB of 23.32MB (0.11MB free) in [com.example.Coverlow]
DEBUG/Application(5221): debug.memory: allocated: 4.00MB of 24.00MB (1.00MB free)
DEBUG/dalvikvm(5221): GC freed 331 objects / 18184 bytes in 68ms
DEBUG/dalvikvm(5221): GC freed 60 objects / 3128 bytes in 68ms
调试/应用程序(5221):调试=================================
调试/应用程序(5221):DEBUG.heap native:在[com.example.Coverflow]中分配了23.32MB(0.08MB空闲)的16.80MB
调试/应用程序(5221):调试。内存:已分配:24.00MB中的4.00MB(1.00MB可用)
调试/dalvikvm(5221):GC在73毫秒内释放842个对象/99256字节
DEBUG/dalvikvm(5221):GC在69ms内释放306个对象/24896字节
退出第五画廊后:
DEBUG/Application(5221): debug. =================================
DEBUG/Application(5221): debug.heap native: allocated 16.80MB of 23.32MB (0.08MB free) in [com.example.Coverflow]
DEBUG/Application(5221): debug.memory: allocated: 4.00MB of 24.00MB (1.00MB free)
DEBUG/dalvikvm(5221): GC freed 842 objects / 99256 bytes in 73ms
DEBUG/dalvikvm(5221): GC freed 306 objects / 24896 bytes in 69ms
DEBUG/Application(5221): debug. =================================
DEBUG/Application(5221): debug.heap native: allocated 16.74MB of 23.32MB (0.11MB free) in [com.example.Coverlow]
DEBUG/Application(5221): debug.memory: allocated: 4.00MB of 24.00MB (1.00MB free)
DEBUG/dalvikvm(5221): GC freed 331 objects / 18184 bytes in 68ms
DEBUG/dalvikvm(5221): GC freed 60 objects / 3128 bytes in 68ms
调试/应用程序(5221):调试=================================
调试/应用程序(5221):DEBUG.heap native:在[com.example.Coverlow]中分配了23.32MB(0.11MB空闲)的16.74MB
调试/应用程序(5221):调试。内存:已分配:24.00MB中的4.00MB(1.00MB可用)
DEBUG/dalvikvm(5221):GC在68毫秒内释放了331个对象/18184字节
DEBUG/dalvikvm(5221):GC在68ms内释放了60个对象/3128字节
似乎在进入画廊时分配了越来越多的内存,但在退出画廊后释放的内存很少。我没有正确清理我的抽屉吗?对于drawables的arrayList中的每个元素,我调用setCallBack(null)并将元素设置为null。这还不够吗?渴望任何洞察力。
谢谢您在gallery 5或gallery 6中加载的图像可能太大而无法加载,并且超出了VM允许的最大大小。您在gallery 5或gallery 6中加载的图像可能太大而无法加载,并且超出了VM允许的最大大小 这些图像是从网络上获取的, 每台功率范围为300K至500K英寸 大小,并存储在 可提取的 从web加载的图像的kb文件大小与此没有直接关系。因为它们被转换成位图,所以对于常规ARGB图像,您需要计算每个图像的宽度*高度*4字节。(宽度和高度以像素为单位) 位图使用本机堆,而本机堆通常不会显示在hprof中。hprof应该只显示对象的数量,即剩余的位图绘制表或位图 我在我的应用程序中使用此代码输出应用程序和本机堆当前使用的内存:
public static void logHeap(Class clazz) {
Double allocated = new Double(Debug.getNativeHeapAllocatedSize())/new Double((1048576));
Double available = new Double(Debug.getNativeHeapSize())/1048576.0);
Double free = new Double(Debug.getNativeHeapFreeSize())/1048576.0);
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(2);
df.setMinimumFractionDigits(2);
Log.d(APP, "debug. =================================");
Log.d(APP, "debug.heap native: allocated " + df.format(allocated) + "MB of " + df.format(available) + "MB (" + df.format(free) + "MB free) in [" + clazz.getName().replaceAll("com.myapp.android.","") + "]");
Log.d(APP, "debug.memory: allocated: " + df.format(new Double(Runtime.getRuntime().totalMemory()/1048576)) + "MB of " + df.format(new Double(Runtime.getRuntime().maxMemory()/1048576))+ "MB (" + df.format(new Double(Runtime.getRuntime().freeMemory()/1048576)) +"MB free)");
System.gc();
System.gc();
// don't need to add the following lines, it's just an app specific handling in my app
if (allocated>=(new Double(Runtime.getRuntime().maxMemory())/new Double((1048576))-MEMORY_BUFFER_LIMIT_FOR_RESTART)) {
android.os.Process.killProcess(android.os.Process.myPid());
}
}
在开发过程中,我在开始或完成活动时调用它
logHeap(this.getClass());
这里有一些信息性的链接——通常这里有很多关于这个主题的帖子