Android中存在奇怪的内存问题

时间:2011-08-06 03:15:47

标签: java android memory memory-management

我在尝试监视系统内存时遇到问题,试图在加载之前猜测Bitmap是否适合内存。 这是我的代码:

public class MemoryCrashTestActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    String url="http://wallpapers-database.com/images/12_wallpaper_xbiz.jpg";

    ArrayList<Bitmap> images= new ArrayList<Bitmap>();
    while(true){
        checkBitmapFitsInMemory(1600,1200,4);
        images.add(getImageBitmapFromUrl(url));
    }
}


public static boolean checkBitmapFitsInMemory(long bmpwidth,long bmpheight, int bmpdensity ){
    long reqsize=bmpwidth*bmpheight*bmpdensity;
    long allocNativeHeap = Debug.getNativeHeapAllocatedSize();

    Log.w("test","Allocated mem="+allocNativeHeap/1024+" of total="+Runtime.getRuntime().maxMemory()/1024+" required= "+reqsize/1024);

    if ((reqsize + allocNativeHeap+3*1024*1024) >= Runtime.getRuntime().maxMemory())
    {
        Log.e("test","Next load will crash due to low memory");
        return false;
    }
    return true;

}


public static Bitmap getImageBitmapFromUrl(String url){
    URL aURL;
    Bitmap result = null;
    try {

        aURL = new URL(url);
        URLConnection conn = aURL.openConnection();
        conn.connect();
        InputStream is = conn.getInputStream();
        result= BitmapFactory.decodeStream(is);
        is.close();


    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
    return result;
}

}

如果我在三星Galaxy S1(运行android 2.3.4)上运行它,那就是输出:

    Allocated mem=7911 of total=65536 required= 7500
    Allocated mem=11663 of total=65536 required= 7500
    Allocated mem=15474 of total=65536 required= 7500
    Allocated mem=19234 of total=65536 required= 7500
    Allocated mem=22986 of total=65536 required= 7500
    Allocated mem=26738 of total=65536 required= 7500
    Allocated mem=30490 of total=65536 required= 7500
    Allocated mem=34242 of total=65536 required= 7500
    Allocated mem=37994 of total=65536 required= 7500
    Allocated mem=41747 of total=65536 required= 7500
    Allocated mem=45499 of total=65536 required= 7500
    Allocated mem=49251 of total=65536 required= 7500
    Allocated mem=53003 of total=65536 required= 7500
    Allocated mem=56755 of total=65536 required= 7500
    Allocated mem=60507 of total=65536 required= 7500
    Next load probably will crash due to low memory
        FATAL EXCEPTION: main
        java.lang.OutOfMemoryError: bitmap size exceeds VM budget
            at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
            at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:573)
            at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:628)
            at com.example.memorycrash.MemoryCrashTestActivity.getImageBitmapFromUrl(MemoryCrashTestActivity.java:56)
            at com.example.memorycrash.MemoryCrashTestActivity.onCreate(MemoryCrashTestActivity.java:26)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
            at android.app.ActivityThread.access$1500(ActivityThread.java:117)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:130)
            at android.app.ActivityThread.main(ActivityThread.java:3687)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:507)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
            at dalvik.system.NativeStart.main(Native Method)

似乎有效。如果我使用HTC野火,输出类似。但是当尝试使用华硕eee pad变换器(Android 3.1)时输出:

        Allocated mem=2585 of total=49152 required= 7500
        Allocated mem=2588 of total=49152 required= 7500
        Allocated mem=2647 of total=49152 required= 7500
        Allocated mem=2655 of total=49152 required= 7500
        Allocated mem=2656 of total=49152 required= 7500
        Allocated mem=2656 of total=49152 required= 7500
        Allocated mem=2656 of total=49152 required= 7500
        Allocated mem=2656 of total=49152 required= 7500
        Allocated mem=2656 of total=49152 required= 7500
        Allocated mem=2656 of total=49152 required= 7500
        Allocated mem=2657 of total=49152 required= 7500
        Allocated mem=2657 of total=49152 required= 7500
        ERROR/dalvikvm-heap(1398): Out of memory on a 3840016-byte allocation.
        08-06 05:05:19.490: WARN/dalvikvm(1398): threadid=1: thread exiting with uncaught exception (group=0x40168760)
            FATAL EXCEPTION: main
            java.lang.OutOfMemoryError
                at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
                at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
                at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:549)
                at com.example.memorycrash.MemoryCrashTestActivity.getImageBitmapFromUrl(MemoryCrashTestActivity.java:56)
                at com.example.memorycrash.MemoryCrashTestActivity.onCreate(MemoryCrashTestActivity.java:26)
                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1048)
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1712)
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1764)
                at android.app.ActivityThread.access$1500(ActivityThread.java:122)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1002)
                at android.os.Handler.dispatchMessage(Handler.java:99)
                at android.os.Looper.loop(Looper.java:132)
                at android.app.ActivityThread.main(ActivityThread.java:4025)
                at java.lang.reflect.Method.invokeNative(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:491)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
                at dalvik.system.NativeStart.main(Native Method)

为什么会这样?

由于

1 个答案:

答案 0 :(得分:1)

在Android 3.0之前,位图存储在本机堆中,这就是为什么你看到Debug.getNativeHeapAllocatedSize();正在提升。

从3.0开始,它们存储在java堆中。

Watch this from the 10 minute mark.

可能你需要使用something like this来获取内存,我无法测试,因为3.0模拟器太慢了。