什么 is/are GC 根对象引用 Java 外部和内部 类?
What is/are GC root objects referencing Java outer and inner classes?
所以我对 android 中的内存泄漏进行了大量研究,并阅读了许多 Whosebug post。我仍然不明白的是,根据 Medium 和 Whosebug posts(下面提到的链接),如果我将 activity 的上下文传递给 Recyclerview 的适配器并将其存储为全局变量在适配器中,我的 activity 和适配器仍然有资格进行垃圾回收。这是因为 没有 GC roots 引用适配器或我的 activity (一旦它被销毁),所以两者都将被垃圾收集 (示例 1)。但是,为什么不对内部 classes 应用相同的情况?我知道他们持有对他们持有的 class 的隐式引用,但是如果 activity(在这种情况下持有 class)被销毁,即使内部 class 仍在执行一些异步任务,不应该 没有 GC 根 指向它们中的任何一个吗? (holding or the inner class) 所以他们两个都应该收集垃圾? (示例 2)。
示例 1:(在 activity 被销毁后符合 GC 条件):
public class MyAdaptor extends RecyclerView.Adaptor<>{
public Context context;
public MyAdaptor(Context context){
this.context=context;
}
}
public MyActivity extends AppCompatActivity {
private MyAdaptor myAdaptor;
@Override
protected void onCreate(Bundle savedInstanceState) {
//some code
myAdaptor=new MyAdaptor(this);
}
}
示例 2:(activity 被销毁后不符合 GC 条件):
public MyHoldingActivity extends AppCompatActivity {
private MyInnerClass myInnerClass;
@Override
protected void onCreate(Bundle savedInstanceState) {
myInnerClass=new MyInnerClass();
}
class MyInnerClass{
//executing some long Async Task
}
}
我提到的两个 post 的链接如下:
https://medium.com/@oznusem/circular-dependency-in-android-should-i-worry-about-it-814660ac79ec
抱歉,如果我没有说清楚我的问题,这是我在 Whosebug 上的第一个 post。
假设 AsyncTask
引用了您的内部 class,那么:
如果一个Activity
的内部class是运行一个AsyncTask
,即使Activity
完成了,GC也无法回收 Activity
因为内部 class 引用了 Activity
而 AsyncTask
引用了内部 class 和 Android的内部线程管理器引用了 AsyncTask
。但是,一旦 AsyncTask
完成,GC 就可以回收 Activity
,因为内部线程管理器将不再引用 AsyncTask
.
这并不是真正的内存泄漏,因为这只是暂时的情况。 Activity
最终会被回收。真正的 "memory leaks" 发生在对象 永远不会 被 GC 回收时。最终,此类内存泄漏会消耗所有可用内存并导致长 运行 应用程序崩溃并出现 OutOfMemoryException
.
您可以通过取消 Activity
的 onDestroy()
中的 AsyncTask
来防止这种情况发生。
希望这能回答您的问题。
所以我对 android 中的内存泄漏进行了大量研究,并阅读了许多 Whosebug post。我仍然不明白的是,根据 Medium 和 Whosebug posts(下面提到的链接),如果我将 activity 的上下文传递给 Recyclerview 的适配器并将其存储为全局变量在适配器中,我的 activity 和适配器仍然有资格进行垃圾回收。这是因为 没有 GC roots 引用适配器或我的 activity (一旦它被销毁),所以两者都将被垃圾收集 (示例 1)。但是,为什么不对内部 classes 应用相同的情况?我知道他们持有对他们持有的 class 的隐式引用,但是如果 activity(在这种情况下持有 class)被销毁,即使内部 class 仍在执行一些异步任务,不应该 没有 GC 根 指向它们中的任何一个吗? (holding or the inner class) 所以他们两个都应该收集垃圾? (示例 2)。
示例 1:(在 activity 被销毁后符合 GC 条件):
public class MyAdaptor extends RecyclerView.Adaptor<>{
public Context context;
public MyAdaptor(Context context){
this.context=context;
}
}
public MyActivity extends AppCompatActivity {
private MyAdaptor myAdaptor;
@Override
protected void onCreate(Bundle savedInstanceState) {
//some code
myAdaptor=new MyAdaptor(this);
}
}
示例 2:(activity 被销毁后不符合 GC 条件):
public MyHoldingActivity extends AppCompatActivity {
private MyInnerClass myInnerClass;
@Override
protected void onCreate(Bundle savedInstanceState) {
myInnerClass=new MyInnerClass();
}
class MyInnerClass{
//executing some long Async Task
}
}
我提到的两个 post 的链接如下: https://medium.com/@oznusem/circular-dependency-in-android-should-i-worry-about-it-814660ac79ec
抱歉,如果我没有说清楚我的问题,这是我在 Whosebug 上的第一个 post。
假设 AsyncTask
引用了您的内部 class,那么:
如果一个Activity
的内部class是运行一个AsyncTask
,即使Activity
完成了,GC也无法回收 Activity
因为内部 class 引用了 Activity
而 AsyncTask
引用了内部 class 和 Android的内部线程管理器引用了 AsyncTask
。但是,一旦 AsyncTask
完成,GC 就可以回收 Activity
,因为内部线程管理器将不再引用 AsyncTask
.
这并不是真正的内存泄漏,因为这只是暂时的情况。 Activity
最终会被回收。真正的 "memory leaks" 发生在对象 永远不会 被 GC 回收时。最终,此类内存泄漏会消耗所有可用内存并导致长 运行 应用程序崩溃并出现 OutOfMemoryException
.
您可以通过取消 Activity
的 onDestroy()
中的 AsyncTask
来防止这种情况发生。
希望这能回答您的问题。