的OutOfMemoryError虽然虚拟机有足够的可用内存 [英] OutOfMemoryError although vm has enough free memory

查看:309
本文介绍了的OutOfMemoryError虽然虚拟机有足够的可用内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到这个奇怪的OutOfMemoryError发生虽然dalvikvm报告足够的堆空间。日志:

  12-09 14:16:05.527:D / dalvikvm(10040):GC_FOR_ALLOC释放551K,21%的自由38000K / 47687K,暂停173ms,总173ms
12-09 14:16:05.527:I / dalvikvm堆(10040):成长堆(破片的情况下),以38.369MB为858416字节分配
12-09 14:16:05.699:D / dalvikvm(10040):GC_FOR_ALLOC释放6K,免费38832K / 48583K,暂停169ms,共169ms 21%
12-09 14:16:05.894:D / dalvikvm(10040):GC_FOR_ALLOC释放103K,免费38929K / 48583K,暂停169ms,共169ms 20%
12-09 14:16:05.894:I / dalvikvm堆(10040):强制收集SoftReferences为858416字节分配
12-09 14:16:06.074:D / dalvikvm(10040):GC_BEFORE_OOM释放6K,20%的自由38922K / 48583K,暂停182ms,总182ms
12-09 14:16:06.074:E / dalvikvm堆(10040):内存在858416字节分配。
12-09 14:16:06.074:I / dalvikvm(10040):AsyncTask的#2PRIO = 5 TID = 17 RUNNABLE
12-09 14:16:06.074:I / dalvikvm(10040):|组=主SCOUNT = 0 dsCount = 0的obj = 0x42013580自我= 0x5f2a48d8
12-09 14:16:06.074:I / dalvikvm(10040):| sysTid = 10101漂亮= 10 sched的= 0/0 CGRP =应用程序/ bg_non_interactive手柄= 1591062136
12-09 14:16:06.074:I / dalvikvm(10040):| schedstat =(7305663992 4216491759 5326)UTM = 697 STM = 32核心= 1
12-09 14:16:06.074:I / dalvikvm(10040):在android.graphics.BitmapFactory.nativeDe codeStream(本机方法)
12-09 14:16:06.074:I / dalvikvm(10040):在android.graphics.BitmapFactory.de codeStream(BitmapFactory.java:619)
12-09 14:16:06.074:I / dalvikvm(10040):在android.graphics.BitmapFactory.de codeStream(BitmapFactory.java:691)
 

正如你可以看到内存不足时约GC后10MB可用内存dalvikvm报道权利之前。分配为800K位图。我怀疑是有GC和位图解码之间的竞争条件在这里,因为的Dalvik的报告可用内存不低于8MB的可用内存,在过去20-30秒的崩溃之前的所有日志报表。

这个问题发生在三星Galaxy Tab 2 10.1运行Android 4.1.2。 我使用的谷歌I / O的应用程序(2012)的ImageFetcher类的修改版本,所以装载图像时,优化的采样大小选择,我已经在做的东西一样inJustDe codeBounds。

根据在管理位图内存的Andr​​oid文档中的Dalvik的分配位图的像素数据堆(由于Android 3.0),所以为什么解码位图会与10MB的可用内存的内存不足

在有没有人看到了这一点,也可以有一个想法是怎么回事?

编辑: 每个请求<一href="https://$c$c.google.com/p/iosched/source/browse/android/src/com/google/android/apps/iosched/util/ImageFetcher.java?name=2012">here从谷歌I / O 2012的应用程序图像加载code。 在我的应用程序,我只是想问

  mImageFetcher.loadImage(myUrl,myImageView);
 

EDIT2: 从上面的链接提取的相关图像解码方法,使清楚,我已经使用的样本大小的优化:

 公共静态位图德codeSampledBitmapFromDescriptor(
        的FileDescriptor文件描述符,INT reqWidth,诠释reqHeight){

    //第一代code与inJustDe codeBounds = true来检查尺寸
    最后BitmapFactory.Options选项=新BitmapFactory.Options();
    options.inJustDe codeBounds = TRUE;
    BitmapFactory.de codeFileDescriptor(文件描述符,空,期权);

    //计算inSampleSize
    options.inSampleSize = calculateInSampleSize(选项,reqWidth,
            reqHeight);

    与inSampleSize集//德code位图
    options.inJustDe codeBounds = FALSE;
    返回BitmapFactory
            .DE codeFileDescriptor(文件描述符,空,期权);
}

公共静态INT calculateInSampleSize(BitmapFactory.Options选项,
        INT reqWidth,诠释reqHeight){
    //原始高度和宽度的图像
    最终诠释身高= options.outHeight;
    最终诠释宽度= options.outWidth;
    INT inSampleSize = 1;

    如果(高度&GT; reqHeight ||宽度GT; reqWidth){
        //计算高度和宽度的比例来要求的高度和
        // 宽度
        最终诠释heightRatio = Math.round((浮点)高度
                /(浮点)reqHeight);
        最终诠释widthRatio = Math.round((浮点)宽/(浮点)reqWidth);

        //选择最小比例为inSampleSize值,这将
        // 保证
        //与两个尺寸大于或等于所述最终图像
        //请求的高度和宽度。
        inSampleSize = heightRatio&LT; widthRatio? heightRatio:widthRatio;

        //这提供了一些额外的逻辑,如果图像有一个奇怪
        //宽高比。例如,全景可以具有大得多的
        //宽度比高度。在这种情况下,总像素可能还是
        //最终会被过大,使之与记忆,所以我们应该
        //更积极与样本下的图像(=大
        // inSampleSize)。

        最终浮动totalPixels =宽*高;

        //任何超过2倍的像素要求,我们将品尝下来
        // 进一步。
        最终浮动totalReqPixelsCap = reqWidth * reqHeight * 2;

        而(totalPixels /(inSampleSize * inSampleSize)&GT; totalReqPixelsCap){
            inSampleSize ++;
        }
    }
    返回inSampleSize;
}
 

解决方案

好像ICS和更高的Andr​​oid版本不会让你的虚拟机去堆的总大小。我已经看到了同样的事情在我的应用程序,

您可以添加

 安卓largeHeap =真
 

要你和lt;应用>这使您的应用程序一个更大的堆。不是很好,但工程...

I am getting this weird OutOfMemoryError that occurs although the dalvikvm reports enough heap space. Logs:

12-09 14:16:05.527: D/dalvikvm(10040): GC_FOR_ALLOC freed 551K, 21% free 38000K/47687K, paused 173ms, total 173ms
12-09 14:16:05.527: I/dalvikvm-heap(10040): Grow heap (frag case) to 38.369MB for 858416-byte allocation
12-09 14:16:05.699: D/dalvikvm(10040): GC_FOR_ALLOC freed 6K, 21% free 38832K/48583K, paused 169ms, total 169ms
12-09 14:16:05.894: D/dalvikvm(10040): GC_FOR_ALLOC freed 103K, 20% free 38929K/48583K, paused 169ms, total 169ms
12-09 14:16:05.894: I/dalvikvm-heap(10040): Forcing collection of SoftReferences for 858416-byte allocation
12-09 14:16:06.074: D/dalvikvm(10040): GC_BEFORE_OOM freed 6K, 20% free 38922K/48583K, paused 182ms, total 182ms
12-09 14:16:06.074: E/dalvikvm-heap(10040): Out of memory on a 858416-byte allocation.
12-09 14:16:06.074: I/dalvikvm(10040): "AsyncTask #2" prio=5 tid=17 RUNNABLE
12-09 14:16:06.074: I/dalvikvm(10040):   | group="main" sCount=0 dsCount=0 obj=0x42013580 self=0x5f2a48d8
12-09 14:16:06.074: I/dalvikvm(10040):   | sysTid=10101 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1591062136
12-09 14:16:06.074: I/dalvikvm(10040):   | schedstat=( 7305663992 4216491759 5326 ) utm=697 stm=32 core=1
12-09 14:16:06.074: I/dalvikvm(10040):   at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
12-09 14:16:06.074: I/dalvikvm(10040):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:619)
12-09 14:16:06.074: I/dalvikvm(10040):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:691)

As you can see right before the outofmemory occurs the dalvikvm reports about 10mb free memory after gc. The allocation is for a 800k bitmap. I doubt that there is a race condition between gc and bitmap decoding here, because the reported free memory of dalvik didn't drop below 8mb free memory in all log statements of the last 20-30 seconds before the crash.

The problem occurs on a Samsung Galaxy Tab 2 10.1 running Android 4.1.2. I'm using a modified version of the ImageFetcher classes from the Google I/O app (2012), so I'm already doing stuff like inJustDecodeBounds when loading images to optimize sampleSize option.

As per documentation in Managing Bitmap Memory Android allocates Bitmap pixel data in the dalvik heap (since Android 3.0), so why does decoding the bitmap cause an outofmemory with 10mb free memory?

Has anyone seen this before or may have an idea what's happening?

EDIT: Per request here is the image loading code from the Google I/O app 2012. In my app I am just calling

mImageFetcher.loadImage(myUrl, myImageView);

EDIT2: The relevant image decoding methods extracted from above link to make clear that I am already using sample size optimizations:

public static Bitmap decodeSampledBitmapFromDescriptor(
        FileDescriptor fileDescriptor, int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth,
            reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory
            .decodeFileDescriptor(fileDescriptor, null, options);
}

public static int calculateInSampleSize(BitmapFactory.Options options,
        int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        // Calculate ratios of height and width to requested height and
        // width
        final int heightRatio = Math.round((float) height
                / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will
        // guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

        // This offers some additional logic in case the image has a strange
        // aspect ratio. For example, a panorama may have a much larger
        // width than height. In these cases the total pixels might still
        // end up being too large to fit comfortably in memory, so we should
        // be more aggressive with sample down the image (=larger
        // inSampleSize).

        final float totalPixels = width * height;

        // Anything more than 2x the requested pixels we'll sample down
        // further.
        final float totalReqPixelsCap = reqWidth * reqHeight * 2;

        while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
            inSampleSize++;
        }
    }
    return inSampleSize;
}

解决方案

It seems like ICS and later Android versions are not letting your VM go to the total size of the heap. I've seen the same thing in my app,

You can add

android:largeHeap="true" 

to your <application> which gives your app a much larger heap. Not nice but works...

这篇关于的OutOfMemoryError虽然虚拟机有足够的可用内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆