被摧毁的活动的垃圾收集/旧活动的破坏

时间:2015-07-31 10:38:24

标签: java android garbage-collection

在研究活动时,我惊讶地发现即使在高内存压力下它们也没有被销毁和垃圾收集(GC)(在三星GT-l9505,Android 4.4.2上测试)

我写了一个简单的Activity,包含一个ImageView(带有〜16Mb的关联位图)和一个Button来测试一些东西。这是代码:

public class MainActivity extends Activity implements View.OnClickListener {

    private byte[] hugeMemoryUse;

    @Override
    public void onCreate(Bundle saved) {
        Log.d("test_activity", "Activity created");
        super.onCreate(saved);
        hugeMemoryUse = new byte[10 * 1000 * 1000];
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        ImageView imageView = (ImageView) findViewById(R.id.huge_image);
        Bitmap bmp = ((BitmapDrawable)getResources().getDrawable(R.drawable.images)).getBitmap();
        Bitmap bmp2 = Bitmap.createScaledBitmap(bmp,bmp.getWidth()*3,bmp.getHeight()*3,false);
        Log.d("test_activity","Width = " + bmp2.getWidth() + ", Height = "  + bmp2.getHeight());
        imageView.setImageBitmap(bmp2);
        button.setText("click to add activity");
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        startActivity(new Intent(this, MainActivity.class));
    }

    @Override
    public void onStop() {
        super.onStop();
        if (isFinishing()) {
            Log.d("test_activity", "Finishing");
        }
        Log.d("test_activity", "Activity stopped");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("test_activity", "Activity destroyed");
    }
}

单击该按钮时,我会在当前按钮上创建一个新的MainActivity。如您所见,Activity还包含对10Mb字节数组的引用。此引用不会故意清除。

现在,如果我多次按下该按钮,应用程序最终会因OutOfMemoryException而崩溃。这是我多次点击按钮时的日志:

07-31 12:06:44.919  27401-27401/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:06:44.939  27401-27401/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 44K, 35% free 17261K/26284K, paused 14ms, total 14ms
07-31 12:06:44.949  27401-27401/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 30.263MB for 10000016-byte allocation
07-31 12:06:44.999  27401-27401/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 20K, 21% free 28831K/36052K, paused 12ms, total 12ms
07-31 12:06:45.019  27401-27401/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 48.618MB for 16350028-byte allocation
07-31 12:06:45.029  27401-27401/test.testactivitygc D/test_activity﹕ Width = 2403, Height = 1701
07-31 12:06:48.473  27401-27401/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:06:48.483  27401-27401/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 1794K, 18% free 43057K/52020K, paused 15ms, total 15ms
07-31 12:06:48.503  27401-27401/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 54.455MB for 10000016-byte allocation
07-31 12:06:48.533  27401-27401/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 12% free 54610K/61788K, paused 14ms, total 14ms
07-31 12:06:48.563  27401-27401/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 71.792MB for 16350028-byte allocation
07-31 12:06:48.573  27401-27401/test.testactivitygc D/test_activity﹕ Width = 2403, Height = 1701
07-31 12:06:48.843  27401-27401/test.testactivitygc D/test_activity﹕ Activity stopped
07-31 12:06:54.478  27401-27401/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:06:54.488  27401-27401/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 1786K, 12% free 68821K/77756K, paused 19ms, total 19ms
07-31 12:06:54.519  27401-27401/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 79.615MB for 10000016-byte allocation
07-31 12:06:54.559  27401-27401/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 9% free 80374K/87524K, paused 16ms, total 16ms
07-31 12:06:54.579  27401-27401/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 96.953MB for 16350028-byte allocation
07-31 12:06:54.589  27401-27401/test.testactivitygc D/test_activity﹕ Width = 2403, Height = 1701
07-31 12:06:54.889  27401-27401/test.testactivitygc D/test_activity﹕ Activity stopped
07-31 12:06:56.530  27401-27401/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:06:56.560  27401-27401/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 1789K, 9% free 94584K/103492K, paused 23ms, total 23ms
07-31 12:06:56.581  27401-27401/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 104.774MB for 10000016-byte allocation
07-31 12:06:56.611  27401-27401/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 7% free 106137K/113260K, paused 17ms, total 17ms
07-31 12:06:56.641  27401-27401/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 122.112MB for 16350028-byte allocation
07-31 12:06:56.651  27401-27401/test.testactivitygc D/test_activity﹕ Width = 2403, Height = 1701
07-31 12:06:56.831  27401-27401/test.testactivitygc D/test_activity﹕ Activity stopped
07-31 12:06:57.912  27401-27401/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:06:57.932  27401-27401/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 1785K, 7% free 120347K/129228K, paused 23ms, total 23ms
07-31 12:06:57.932  27401-27401/test.testactivitygc I/dalvikvm-heap﹕ Forcing collection of SoftReferences for 10000016-byte allocation
07-31 12:06:57.972  27401-27401/test.testactivitygc D/dalvikvm﹕ GC_BEFORE_OOM freed 14K, 7% free 120333K/129228K, paused 35ms, total 35ms
07-31 12:06:57.972  27401-27401/test.testactivitygc E/dalvikvm-heap﹕ Out of memory on a 10000016-byte allocation.
07-31 12:06:57.972  27401-27401/test.testactivitygc E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: test.testactivitygc, PID: 27401
    java.lang.OutOfMemoryError
            at test.testactivitygc.MainActivity.onCreate(MainActivity.java:27)
            at android.app.Activity.performCreate(Activity.java:5426)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2269)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
            at android.app.ActivityThread.access$900(ActivityThread.java:161)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:157)
            at android.app.ActivityThread.main(ActivityThread.java:5356)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
            at dalvik.system.NativeStart.main(Native Method)

可以看到,每次创建一个新的Activity时,都会在堆上分配26 Mb(字节数组为10 Mb,位图为16 Mb)。当Heap变大时,我希望Android能够摧毁堆栈上的Activties。

但是! 堆栈上的活动不会被破坏!它们保留在这里,并且不会破坏位图和字节数组。即使进程在内存上运行非常低。这不是我对Android的预期。 为什么会出现这种情况?另外,我知道好的做法会要求我们清除未使用的引用(在onPause,onStop或onDestroy中),但这里甚至没有调用onDestroy

另一方面,当我改变屏幕的方向时,活动会被破坏。 Heap仍然变大,但最终变得稳定,当我最老的Activity是GC时我想。

这是Heap稳定时的一次迭代:

07-31 12:18:08.816    7797-7797/test.testactivitygc D/test_activity﹕ Activity stopped
07-31 12:18:08.816    7797-7797/test.testactivitygc D/test_activity﹕ Activity destroyed
07-31 12:18:08.826    7797-7797/test.testactivitygc W/ApplicationPackageManager﹕ getCSCPackageItemText()
07-31 12:18:08.826    7797-7797/test.testactivitygc I/PersonaManager﹕ getPersonaService() name persona_policy
07-31 12:18:08.826    7797-7797/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:18:08.836    7797-7797/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 27540K, 34% free 68806K/103488K, paused 13ms, total 13ms
07-31 12:18:08.836    7797-7797/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 79.601MB for 10000016-byte allocation
07-31 12:18:08.876    7797-7797/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 10K, 23% free 80357K/103488K, paused 14ms, total 15ms
07-31 12:18:08.886    7797-7797/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 96.936MB for 16350028-byte allocation
07-31 12:18:08.886    7797-7797/test.testactivitygc D/test_activity﹕ Width = 2403, Height = 1701

最后,我在手机的开发者选项下选中了“不要保持活动”选项。旧活动会被持续销毁,但在这里,堆增长并最终变得稳定。这是日志:

07-31 12:23:05.326  13512-13512/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:23:05.346  13512-13512/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 63K, 35% free 17261K/26284K, paused 14ms, total 14ms
07-31 12:23:05.356  13512-13512/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 30.263MB for 10000016-byte allocation
07-31 12:23:05.406  13512-13512/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 20K, 21% free 28831K/36052K, paused 11ms, total 11ms
07-31 12:23:05.436  13512-13512/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 48.618MB for 16350028-byte allocation
07-31 12:23:05.446  13512-13512/test.testactivitygc D/test_activity﹕ Width = 2403, Height = 1701
07-31 12:23:08.108  13512-13512/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:23:08.128  13512-13512/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 1796K, 18% free 43056K/52020K, paused 17ms, total 17ms
07-31 12:23:08.148  13512-13512/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 54.455MB for 10000016-byte allocation
07-31 12:23:08.188  13512-13512/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 12% free 54609K/61788K, paused 16ms, total 16ms
07-31 12:23:08.218  13512-13512/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 71.792MB for 16350028-byte allocation
07-31 12:23:08.218  13512-13512/test.testactivitygc D/test_activity﹕ Width = 2403, Height = 1701
07-31 12:23:08.509  13512-13512/test.testactivitygc D/test_activity﹕ Activity stopped
07-31 12:23:08.519  13512-13512/test.testactivitygc D/test_activity﹕ Activity destroyed
07-31 12:23:10.060  13512-13512/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:23:10.090  13512-13512/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 1787K, 12% free 68819K/77756K, paused 27ms, total 27ms
07-31 12:23:10.110  13512-13512/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 79.614MB for 10000016-byte allocation
07-31 12:23:10.150  13512-13512/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 15K, 9% free 80363K/87524K, paused 18ms, total 19ms
07-31 12:23:10.180  13512-13512/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 96.942MB for 16350028-byte allocation
07-31 12:23:10.180  13512-13512/test.testactivitygc D/test_activity﹕ Width = 2403, Height = 1701
07-31 12:23:10.461  13512-13512/test.testactivitygc D/test_activity﹕ Activity stopped
07-31 12:23:10.471  13512-13512/test.testactivitygc D/test_activity﹕ Activity destroyed
07-31 12:23:11.452  13512-13512/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:23:11.482  13512-13512/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 1790K, 9% free 94572K/103492K, paused 28ms, total 28ms
07-31 12:23:11.502  13512-13512/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 104.763MB for 10000016-byte allocation
07-31 12:23:11.542  13512-13512/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 25768K, 30% free 80363K/113260K, paused 17ms, total 17ms
07-31 12:23:11.542  13512-13512/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 96.943MB for 16350028-byte allocation
07-31 12:23:11.552  13512-13512/test.testactivitygc D/test_activity﹕ Width = 2403, Height = 1701
07-31 12:23:11.842  13512-13512/test.testactivitygc D/test_activity﹕ Activity stopped
07-31 12:23:11.852  13512-13512/test.testactivitygc D/test_activity﹕ Activity destroyed
07-31 12:23:15.646  13512-13512/test.testactivitygc D/test_activity﹕ Activity created
07-31 12:23:15.666  13512-13512/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 1787K, 17% free 94573K/113260K, paused 21ms, total 21ms
07-31 12:23:15.666  13512-13512/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 104.763MB for 10000016-byte allocation
07-31 12:23:15.696  13512-13512/test.testactivitygc D/dalvikvm﹕ GC_FOR_ALLOC freed 25768K, 30% free 80363K/113260K, paused 15ms, total 15ms
07-31 12:23:15.706  13512-13512/test.testactivitygc I/dalvikvm-heap﹕ Grow heap (frag case) to 96.943MB for 16350028-byte allocation
07-31 12:23:15.716  13512-13512/test.testactivitygc D/test_activity﹕ Width = 2403, Height = 1701

现在,我想知道是否由于流程差异可以解释这个问题?在我测试应用程序时,我猜内存管理可能有点不同。 (这里我没有调试,只是运行应用程序) 有人告诉我,Android和旧版本之间存在很大差异。但是为什么Android更喜欢崩溃而不是冒充一些旧的活动?

那么处理这个问题的正确方法是什么?手动释放onPause / onStop中的每个引用?

0 个答案:

没有答案