Странная проблема с памятью в Android - PullRequest
0 голосов
/ 06 августа 2011

У меня проблема при попытке мониторинга системной памяти, пытающейся угадать, помещается ли растровое изображение в память перед загрузкой. Вот мой код:

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;
}

}

Если я запустил его на Samsung 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 Wildfire. Но при попытке с преобразователем Asus 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 Ответ

1 голос
/ 06 августа 2011

До Android 3.0 растровые изображения хранились в собственной куче, поэтому вы видите, что Debug.getNativeHeapAllocatedSize(); поднимается.

Начиная с 3.0 они хранятся в куче java.

Наблюдайте это с 10-минутной отметки.

Возможно, вам понадобится что-то вроде этого , чтобы получить использование памяти, я не могу проверить, так как эмулятор 3.0 слишком медленный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...