Os objetos complementares permanecem na memória durante o ciclo de vida do aplicativo

8

No Kotlin, você pode criar um singleton usando um objeto complementar:

class MyClass {
   companion object {
        fun doSomething() {

        }
    }
}

De acordo com os documentos da Kotlin, ele afirma:

Observe que, mesmo que os membros dos objetos complementares pareçam membros estáticos em outros idiomas, em tempo de execução, eles ainda são membros da instância de objetos reais ...

https://kotlinlang.org/docs/reference/object-declarations.html

Isso significa que, depois de usar uma função no objeto complementar, a instância da classe (MyClass) permanece na memória durante todo o ciclo de vida do aplicativo? Existe uma maneira no Android Studio de verificar se esse é o caso?

AndroidDev
fonte
Você pode fornecer o link para o documento que você referiu?
Sonu Sanjeev
Vinculado adicionado à postagem.
AndroidDev 10/01

Respostas:

6

A instância da classe (MyClass) permanece na memória durante todo o ciclo de vida do aplicativo ?

Objeto complementar na JVM

em kotlin

class MyClass {
   companion object {
        fun doSomething() {

        }
    }
}

MyClass (Kotlin) convertido na JVM

public final class MyClass {
   public static final MyClass.Companion Companion = new MyClass.Companion(null);

   public static final class Companion {
      public final void doSomething() {
      }

      private Companion() {
      }

      public Companion() {
         this();
      }
   }
}

Como o código acima, companion objecté declarado como Companionclasse na JVM e é criado como staticcampo dentro da MyClassclasse. Assim, não é coletado pelo gc. Portanto, a memória do objeto (Companion) é mantida durante o ProcessLifecycle. static final objectnão é liberado no caso normal.

Em conclusão, se referida à MyClass.Companioninstância no aplicativo, essa instância não será coletada como lixo. (em Classloaders gerais).

* Se não for referido à MyClass.Companioninstância no aplicativo, poderá ser removido pelo recurso de redução de código .

Existe uma maneira no Android Studio de verificar se esse é o caso?

Você pode ver através do android studio> profiler> Heap dump.

Referência

Ethan Choi
fonte
Boa resposta! Mas como você encontrou o código "MyClass (Kotlin) convertido na JVM"?
Astha 23/01
0

Como você parece saber, a resposta acima também deixa claro que os objetos complementares são traduzidos para classes, e a classe que os declara mantém uma referência estática ao objeto da classe complementar, algo como a seguir:

public static final MyClass.Companion Companion = new MyClass.Companion(null);

Agora a pergunta

Os objetos complementares permanecem na memória durante o ciclo de vida do aplicativo

como a classe declarante possui uma staticreferência à classe complementar, a pergunta se reduz ao tempo de vida dos staticcampos na jvm classe a resposta está na especificação da JVM , mas a especificação é um pouco seca na explicação, por isso estou adicionando alguns trechos do livro Inside a Java Virtual Machine .

Como no seu exemplo, digamos que temos um classobjeto complementar com nada além de um único.

A primeira pergunta é quando um objeto da classe complementar será criado? ou quando os staticcampos são inicializados?

texto relevante do livro . (por contexto, o livro está falando sobre o procedimento de carregamento de classe)

Inicialização

A etapa final necessária para preparar uma classe ou interface para seu primeiro uso ativo é a inicialização, o processo de configuração de variáveis ​​de classe com seus valores iniciais adequados. Como usado aqui, um valor inicial "adequado" é o valor inicial desejado pelo programador para uma variável de classe. Um valor inicial adequado contrasta com o valor inicial padrão dado às variáveis ​​de classe durante a preparação. Como descrito acima, a máquina virtual atribui valores padrão com base apenas no tipo de cada variável. Os valores iniciais adequados, por outro lado, são baseados em algum plano mestre conhecido apenas pelo programador. No código Java, um valor inicial adequado é especificado por meio de um inicializador de variável de classe ou inicializador estático.

Portanto, sabemos que, uma vez MyClasscarregado e inicializado, o objeto da classe complementar será criado.

mas o que causaria o carregamento da JVM MyClass?

A especificação Java Virtual Machine oferece às implementações flexibilidade no tempo de carregamento e vinculação de classe e interface, mas define estritamente o tempo de inicialização. Todas as implementações devem inicializar cada classe e interface em seu primeiro uso ativo. Um uso ativo de uma classe é:

  1. A invocação de um construtor em uma nova instância da classe

  2. A criação de uma matriz que tem a classe como um tipo de elemento

  3. A invocação de um método declarado pela classe (não herdada de uma superclasse)

4 O uso ou atribuição de um campo declarado pela classe (não herdado de uma superclasse ou super interface), exceto para campos que são estáticos e finais, e são inicializados por uma expressão constante em tempo de compilação

Portanto, conforme o quarto ponto, quando você faz MyClass.foo()do kotlin ou MyClass.Companion.foo(), nesse momento, MyClassele estará carregado e pronto. (Provavelmente muito cedo)

Observe que, neste ponto, nenhum objeto MyClassexiste, ou seja, não usamos expressão MyClass().

Isso significa que os staticcampos permanecerão na memória enquanto o aplicativo estiver em execução?

Eles podem ser coletados como lixo se o tipo de declaração for descarregado; no nosso caso, se a JVM ou ART (no android) descarregar MyClass, existe a possibilidade de que o objeto complementar seja coletado como lixo.

A JVM Spec tem o seguinte a dizer sobre o descarregamento de classe

Uma implementação da linguagem de programação Java pode descarregar classes.

Uma classe ou interface pode ser descarregada se, e somente se, o seu carregador de classes definidor puder ser recuperado pelo coletor de lixo, conforme discutido em §12.6.

Classes e interfaces carregadas pelo carregador de inicialização não podem ser descarregadas.

Na aula de praticidade, o descarregamento quase (eu disse quase) nunca acontece; portanto , os objetos complementares permanecerão na memória durante o ciclo de vida do aplicativo .

mightyWOZ
fonte