在研究活动时,我惊讶地发现即使在高内存压力下它们也没有被销毁和垃圾收集(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中的每个引用?