【问题标题】:This Kotlin Singleton implementation, will become elegible for Garbage Collection?这个 Kotlin Singleton 实现是否可以用于垃圾收集?
【发布时间】:2018-11-27 03:03:36
【问题描述】:

我让这个类表现得像一个单例(实例没有被保护以再次重新创建):

class FooInteractorFactory(private val someEvent: SomeEvent) {

    companion object {

        lateinit var fooFactory: FooInteractorFactory

        fun initialize(someEvent: SomeEvent) {
            fooFactory = FooInteractorFactory(someEvent)
        }
    }

    fun createSomeObject(): SomeObject {
        return SomeObject(someEvent)
    }

}

这个“单例”正在这个类中初始化:

class FooImpl : SomeEvent {

    init {
        FooInteractorFactory.initialize(this)
    }

    ...
}

FooImpl 正在生命周期函数 onCreate() 的 Activity 中实例化:

class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
       val foompl = FooImpl()
    }

    ...

}

我的问题是FooInteractorFactorySomeEventSomeObject 其中一些会被泄露或不符合垃圾收集条件?

正如文档所说,

当且仅当垃圾收集器可以回收其定义的类加载器时,才能卸载类或接口。

这将是合格的,但是,我不确定。我只是添加到应用程序 LeakCanary,但是,泄漏从未发生过。

我想根据你们每个人的经验来确定。

编辑

这是 FooInteractorFactory 在反编译的 java 代码中的样子:

public final class FooInteractorFactory {
   private final SomeEvent someEvent;
   @NotNull
   public static FooInteractorFactory fooFactory;

   @NotNull
   public final FooInteractorFactory createSomeObject() {
      return new SomeObject(this.someEvent);
   }

   public FooInteractorFactory(@NotNull SomeEvent someEvent) {
      this.someEvent = someEvent;
   }


   public static final class Companion {
      @NotNull
      public final FooInteractorFactory getFooFactory() {
         return FooInteractorFactory.access$getFooFactory$cp();
      }

      public final void setFooFactory(@NotNull FooInteractorFactory var1) {
         FooInteractorFactory.fooFactory = var1;
      }

      public final void initialize(@NotNull SomeEvent someEvent) {
         ((FooInteractorFactory.Companion)this).setFooFactory(new FooInteractorFactory(someEvent));
      }
  }

}

FooInteractorFactory 是同一个类的静态引用。

【问题讨论】:

    标签: android performance kotlin garbage-collection


    【解决方案1】:

    AFAIK LeakCanary 仅检测泄漏的活动,因此它并非旨在检测所有内存泄漏(最后,现在应该如何对哪个实例进行垃圾收集,哪些不应该?)。

    另外,您作为引用附上的内容是关于Class<?>,而不是关于实例。我的意思是,它说的是整个 Class 定义,它们存储在永久代或元空间中(取决于 Java 版本)。

    关于你的问题:垃圾收集器通常以下一种方式工作 - 它从名为 GC 根的引用开始,然后通过来自这些根的引用遍历所有对象,将它们标记为“活动”,并从所有未标记为活动的对象(我的意思是,不能通过 GC 根获得)。被称为 GC-root 的引用是:

    1. 局部变量
    2. static变量
    3. 活跃Threads
    4. JNI 参考

    我怀疑您提到的任何Class 对象都将从JVM 中卸载,以防您尚未定义自己的ClassLoader 或弄乱它们的生命周期。 谈论实例:

    我让这个类表现得像一个单例(实例没有被保护以再次重新创建)

    如果 comanion 的对象 fooFactory 引用了引用的对象 A,然后用对象 B 重新分配,那么如果 A 没有被任何其他 GC-roots 或通过 GC-roots 可用的中间引用引用,与几个 GC 周期相比,此实例将被垃圾回收。

    所有其他实例也是如此。

    【讨论】:

    • @AndreyLlyunin 谢谢你的回答!好吧,因此,反编译类后,对FooInteractorFactory 的静态引用使其不符合垃圾收集条件,但是,请记住FooInteractorFactory 正在另一个类中使用(未引用,未分配)@987654333 @这个类将被删除,所以他们的成员和用法也一样? (FooInteractorFactory)
    • 谈论 instances - 如果没有被 PermGen 或 Metaspace 中已包含的 Class 对象的静态引用的本地引用直接或传递地引用,它们将被收集(让我们在这里忘记 JNI 和线程)。所以,假设val foompl = FooImpl()只会在MainActivityonCreate方法的上下文中使用,那么在这个方法执行完成后,它会在几个GC周期内被收集。
    • 但是(!)因为FooImpl 请求了一个类FooInteractorFactory 并调用了一个静态方法,该方法使用对自身的引用(对FooImpl)初始化工厂,而不是指向的静态引用FooInteractorFactory 对象(在此对象未引用之前不会被 GC 收集,例如,通过将来调用 initialize 方法),比此 FooImpl 实例可用来自两个 GC 根:FooInteractorFactory 上的静态引用,其中包含 FooImpl 对象作为成员,以及 onCreate 中的局部变量 val foompl = ...
    • 作为总结:FooImpl 实例不会丢失,直到两个事件发生: 1. onCreate 方法执行将完成,指向实例的本地引用 foompl 将是丢失(假设它不会被传递给此方法内具有更长生命周期的对象) 2. 引用 fooFactory 指向 FooInteractorFactory(存储从 init 块传递的 FooImpl 的实例FooImpl) 的值会因为另一个initialize 方法调用FooInteractorFactorycompanion object 而改变它的值。
    猜你喜欢
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 2014-07-24
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多