因此,我经常听到“坚持静态 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 ,就像我在这个示例中如何通过从其布局中保存对 Button
的 static
引用来泄漏 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/