android - 如何强制Android上的内存泄漏导致崩溃?

标签 android android-activity memory-management android-memory

因此,我经常听到“坚持静态 Activity 或 View ,尤其是在长时间运行的 AsyncTask 中会导致内存泄漏并使您的应用程序崩溃”。

但是,我未能在 Android 模拟器中实际证明这一点。

我做错了什么?

public class MainActivity extends AppCompatActivity {

static TextView label;
static List<Activity> sHolder = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ViewGroup vg = findViewById(R.id.blah);
    for (int i=0; i<1000000; i++) {
        ImageView im = new ImageView(this);
        im.setImageDrawable(getApplicationContext().getDrawable(R.drawable.kitten_original));
        vg.addView(im);

        new MyTask(this).execute();
    }

    sHolder.add(this);
}

@Override
protected void onStart() {
    super.onStart();
}

@Override
protected void onStop() {
    super.onStop();
}

@Override
protected void onDestroy() {
    super.onDestroy();
}

class MyTask extends AsyncTask<Void, Void, Void> {

    Activity activity;
    public MyTask(Activity activity) {
        this.activity = activity;
    }
    @Override
    protected Void doInBackground(Void... voids) {
        try {
            Thread.sleep(10000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

不是每次崩溃,我的电脑只是开始有点滞后,它一直看到大约 100 MB 的垃圾收集发生。

我怎样才能真正强制应用程序崩溃? (请不要问我为什么要强制应用程序崩溃,我正在做一些极限测试)

最佳答案

I often hear that "holding on to a static activity or view, especially inside an AsyncTask that is long running will cause a memory leak and crash your app".

这是一个简化的解释。

However, I've been unsuccessfully able to actually prove that in an Android Emulator.

我怀疑这段代码没有运行。在循环执行数百次后,您应该会崩溃,因为您可以拥有的排队 AsyncTasks 数量是有限制的,并且该限制与内存消耗无关。

忽略数百万个 AsyncTasks 和数百万个 ImageViews,您正在通过 sHolder 泄漏 Activity ,就像我在这个示例中如何通过从其布局中保存对 Buttonstatic 引用来泄漏 Activity :

/***
 Copyright (c) 2015 CommonsWare, LLC
 Licensed under the Apache License, Version 2.0 (the "License"); you may not
 use this file except in compliance with the License. You may obtain    a copy
 of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
 by applicable law or agreed to in writing, software distributed under the
 License is distributed on an "AS IS" BASIS,    WITHOUT WARRANTIES OR CONDITIONS
 OF ANY KIND, either express or implied. See the License for the specific
 language governing permissions and limitations under the License.

 Covered in detail in the book _The Busy Coder's Guide to Android Development_
 https://commonsware.com/Android
 */

package com.commonsware.android.button;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;

public class ButtonDemoActivity extends Activity {
  private static Button pleaseDoNotDoThis;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    pleaseDoNotDoThis=(Button)findViewById(R.id.button1);
  }
}

您可以使用 LeakCanary、Android Studio 的堆分析器等来证明发生了泄漏。但是,要证明该泄漏,您需要运行该应用,然后按返回键,然后查看您销毁的 Activity 是否未被垃圾回收。或者,您需要运行该应用程序,旋转屏幕(或进行任何其他类型的配置更改),然后看到您现在有两个 Activity 实例,一个被破坏和泄漏的实例加上一个当前实例。如果您只是运行应用程序而不做任何事情,那么您就没有泄露 Activity — 虽然您有自己的静态引用,Android 也是如此,因为 Activity 在前台并且用户可以看到它。

泄漏本身不会导致崩溃。这只是意味着您正在占用无法用于其他用途的堆空间。最终,您会在某些分配上遇到 OutOfMemoryError。如果您只想因 OutOfMemoryError 崩溃,请尝试分配一些大的 byte[](比如 1GB)。

如果您特别想测试由泄漏 Activity 触发的 OutOfMemoryError,您需要:

  • 让 Activity 分配大量堆空间(例如,1MB byte[]),

  • 像您的 sHolder 列表一样做一些事情,然后

  • 大量旋转屏幕,或者让您自己处于将创建和销毁大量 Activity 实例但不进行垃圾回收的情况,由您的 sHolder

关于android - 如何强制Android上的内存泄漏导致崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52825913/

相关文章:

java - map View 未显示

java - 控制 Linux 中 Java 独立运行的最大数量

linux - 处理器和虚拟/物理地址

java - OS X Lion 上的 Eclipse Indigo 打字延迟

android - HistoryRecord 的 Activity 空闲超时?

android - 当从 Android 中的其他 Activity 返回时, Activity 再次从服务器重新加载全部数据

java - 如何在android中设置定时器?

android - 旋转手机时信息消失

java - Android:如何在本地写入文件并将其保存到下载中

java - Netbeans Android 模拟器未运行程序