安卓内存测试

5
这可能是一个愚蠢的问题,但我似乎在互联网上找不到很多具体信息。
假设我有两个活动:MainActivity和Secondactivity。 MainActivity有一个按钮可以进入Secondactivity。 第二个活动有一个按钮返回到主活动(下面是非常简单的代码)。
我正在尝试理解Android内存管理,这就是为什么我正在进行这个测试的原因。
我的问题:
当我不断地在活动之间来回切换时,在Android Studio中查看内存图表时,我可以看到一个蓝色的图形,它从未回到应用程序启动时分配给它的内存。我是否存在内存泄漏?(可能不是因为这是基本代码)。但是为什么它从来没有回到开始时的原始分配内存呢?
MainActivity只有这个方法:
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button btnTest = (Button) findViewById(R.id.btnTest);
    btnTest.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v)
        {
            Log.i(null, "test");
            finish();
            startActivity(new Intent(MainActivity.this, SecondActivity.class));
        }
    });
}

第二个活动只是返回到第一个活动并创建一些按钮。

public class SecondActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);

    Button btnTest = (Button) findViewById(R.id.btnTest);
    btnTest.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v)
        {
            Log.i(null, "test");
            finish();
            startActivity(new Intent(SecondActivity.this, MainActivity.class));
        }
    });

}

}

enter image description here


不,我没有使用那个。也没有修改清单文件。 - DennisVA
我贴在问题中的代码是应用程序中唯一的代码,非常基础,没有自定义的回退栈实现。 - DennisVA
当您按下“返回”按钮时,您的活动将被销毁,然后您回到上一个活动。我还在onClick方法中编写了finish()语句,以确保它们被销毁,所以这不是相同的事情吗?我是有意创建新实例的。但是垃圾收集器会在一段时间后使堆回到启动时的原始分配内存值,对吗? - DennisVA
我的错,忘了那一部分——由于某种原因我没有看到finish()...但我认为这与finish()没有完全删除Activity有关。我听说onDestroy被调用并不表示对象已经丢失,Android会在一段时间内保留实例以防再次创建。 - cozyconemotel
4个回答

1

你的代码中没有内存泄漏。分配的内存增加的原因是因为你的应用程序需要一些内存来传输到不同的活动中。但是,如果你继续永远运行这段代码,你会看到突然的下降,我已经画出了这个过程:

enter image description here

每次垃圾回收发生时,分配的内存将会减少。然而,如果您有一个内存泄漏,这意味着GC将无法摆脱某些对象。因此,您会看到一个趋势线随着时间的推移而逐渐增加,直到出现内存不足错误。

如何测试?

我建议您使意图在onCreate中被调用,以进行前后无限循环的活动。除非您遇到OutOfMemory错误,否则可能没有内存泄漏。

来自开发人员指南:

随着您在应用程序中分配更多对象,您将强制进行定期垃圾回收,从而在用户体验中创建小的“抽搐”。Android 2.3中引入的并发垃圾收集器有所帮助,但应始终避免不必要的工作。


尝试使用FLAG_ACTIVITY_REORDER_TO_FRONT,然后告诉我发生了什么。 - Ruchir Baronia
不行,因为这没有意义。重新排序只是把即将启动的活动放在最前面,而它已经在最前面了,因为只有一个活动(另一个活动已经明确完成)。 - DennisVA
我使用Genymotion作为模拟器。应该使用真实设备进行内存分析。那就是问题所在。 - DennisVA
@user2395334 噢,这就解释了。如果其他人有同样的问题,你应该添加一个答案 :) - Ruchir Baronia
@user2395334 不用担心 ;) 给你的回答点赞了。 - Ruchir Baronia
显示剩余5条评论

1

我认为问题出在使用Genymotion模拟器上。你应该使用真实设备进行内存分析,而且旧版的内存监视器更加精确。


-1

蓝色图表显示了分配的内存量。

为什么分配的内存会增加

当你在两个活动之间来回切换时,你的应用程序会被分配内存以创建新的活动。

为什么分配的内存不会减少

它不会减少,因为内存在垃圾回收期间被释放。Dalvikvm 将确定何时进行垃圾回收,因此可能会在较长时间内不进行垃圾回收。你可以继续在两个活动之间来回切换,以增加分配的内存,一旦分配的内存足够大,你应该会看到分配的内存量突然下降。

为什么分配的内存会突然下降

当发生垃圾回收时,分配的内存将被释放。如果你在 Android Studio 中查看 logcat,分配的内存突然下降应该伴随着 Dalvikvm GC_something freed 消息。这意味着垃圾回收已经发生,内存已被释放。你可以通过点击“启动 GC”按钮(蓝色图表左侧)手动触发垃圾回收来观察这种情况的发生。


是的,确实有一些下降,但它并没有完全回到初始分配的内存状态,这就是我不理解的原因... - DennisVA

-1

这只是垃圾回收(GC)的问题。即使您编写最少的代码,框架可能在幕后执行大量工作。实际上,每次单击时您都会显式地创建一些对象。

这里是内存图,您可以看到GC的效果。 enter image description here enter image description here


是的,但你可以看到你的图表总体上保持不变,我的图表升高了,我不知道为什么。由于这个带有两个活动的代码非常简单,并且据我所知没有保持对象存活的引用,因此不存在任何内存泄漏。 - DennisVA
我添加了一张图片,请看一下。 - DennisVA
他的图表通常是上升的。 - Ruchir Baronia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接