Эта реализация Kotlin Singleton станет элегантной для сборки мусора? - PullRequest
0 голосов
/ 27 ноября 2018

У меня этот класс действует как синглтон (экземпляр не защищен для повторного создания):

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() в Деятельности:

class MainActivity : AppCompatActivity() {


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

    ...

}

Мой вопрос здесь FooInteractorFactory, SomeEvent или SomeObject, некоторые из них будутутечка или нет права на сбор мусора?

Как сказано в документации,

Класс или интерфейс могут быть выгружены тогда и только тогда, когда сборщик мусора может вернуть их определяющий загрузчик классов.

это будет иметь право, НО, я не уверен.Я просто добавляю в приложение 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 является статической ссылкой того же класса.

1 Ответ

0 голосов
/ 27 ноября 2018

AFAIK LeakCanary обнаруживает только утечку активности, поэтому он не предназначен для обнаружения всех утечек памяти (наконец, как теперь следует, какой экземпляр должен собирать мусор, а какой нет?).

Кроме того, что выПрикрепил как цитата о Class<?>, а не об экземпляре.Я имею в виду, что в нем говорится о целых Class определениях, которые хранятся в постоянном поколении или в Metaspace (зависит от версии Java).

И по поводу вашего вопроса: сборщик мусора обычно работает следующим образом - он запускаетсяиз ссылок, названных корнями GC, затем проходит через все объекты через ссылки из этих корней, помечает их как «живые» и восстанавливает память от всех объектов, которые не были помечены как живые (я имею в виду, которые недоступны через корни GC).Ссылки, известные как GC-корни:

  1. Локальные переменные
  2. static переменные
  3. Активные Thread s
  4. JNI ссылки

Я сомневаюсь, что любой из Class объектов, которые вы упомянули, будет выгружен из JVM, если вы не определили свой собственный ClassLoader или испортили его жизненный цикл.Говоря об экземплярах:

У меня есть класс, действующий как одноэлементный (экземпляр не защищен для повторного создания)

Если объект команиона fooFactory ссылается наобъект A и затем был переназначен с объектом B, тогда, если на A нет ссылок с любыми другими GC-корнями или промежуточными ссылками, доступными через GC-корни, то в нескольких циклах GC этот экземпляр будет собираться мусором.

То же самое относится ко всем остальным экземплярам.

...