¿Los objetos complementarios permanecen en la memoria durante el ciclo de vida de la aplicación?

8

En Kotlin, puede crear un singleton usando un objeto complementario:

class MyClass {
   companion object {
        fun doSomething() {

        }
    }
}

Según los documentos de Kotlin, dice:

Tenga en cuenta que, aunque los miembros de los objetos complementarios se vean como miembros estáticos en otros idiomas, en el tiempo de ejecución siguen siendo miembros de objetos reales ...

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

¿Significa esto que después de usar una función en el objeto complementario, la instancia de la clase (MyClass) permanece en la memoria durante todo el ciclo de vida de la aplicación? ¿Hay alguna manera en Android Studio para verificar si este es el caso?

AndroidDev
fuente
¿Puedes proporcionar el enlace al documento que refieres?
Sonu Sanjeev
Vinculado agregado a la publicación.
AndroidDev

Respuestas:

6

¿La instancia de la clase (MyClass) permanece en memoria durante todo el ciclo de vida de la aplicación ?

Objeto complementario en JVM

en kotlin

class MyClass {
   companion object {
        fun doSomething() {

        }
    }
}

MyClass (Kotlin) convertido en 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 el código anterior, companion objectse declara como Companionclase en JVM y se crea como staticcampo dentro de la MyClassclase. Por lo tanto, no es recolectado por gc. Por lo tanto, la memoria del objeto (Compañero) se mantiene durante el ProcessLifecycle. static final objectno se lanza en el caso normal.

En conclusión, si se hace referencia a la MyClass.Companioninstancia en la aplicación, esa instancia no se recolectará como basura. (en cargadores de clase generales).

* Si no se hace referencia a la MyClass.Companioninstancia en la aplicación, puede eliminarse mediante la función de reducción de código .

¿Hay alguna manera en Android Studio para verificar si este es el caso?

Puedes ver a través de android studio> profiler> Heap dump.

Referencia

Ethan Choi
fuente
¡Buena respuesta! ¿Pero cómo encontraste el código "MyClass (Kotlin) convertido en JVM"?
Astha
0

Como parece saber y la respuesta anterior también deja en claro que los objetos complementarios se traducen a clases, y la clase que los declara tiene una referencia estática al objeto de la clase complementaria, algo como lo siguiente:

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

Ahora la pregunta

¿Los objetos complementarios permanecen en la memoria durante el ciclo de vida de la aplicación?

debido a que la clase declarante tiene una staticreferencia a la clase compañera, la pregunta se reduce al tiempo de vida de los staticcampos en jvm classy la respuesta se encuentra en la especificación JVM , pero la especificación es un poco seca en la explicación, así que estoy agregando algunos fragmentos del libro Inside La máquina virtual Java .

Como en su ejemplo, digamos que tenemos un classobjeto que no tiene nada más que compañero.

La primera pregunta es cuándo se creará un objeto de clase compañera. o cuando staticse inicializan los campos?

Texto relevante del libro . (por contexto, el libro habla sobre el procedimiento de carga de clases)

Inicialización

El último paso requerido para preparar una clase o interfaz para su primer uso activo es la inicialización, el proceso de establecer las variables de clase en sus valores iniciales adecuados. Como se usa aquí, un valor inicial "apropiado" es el valor inicial deseado del programador para una variable de clase. Un valor inicial adecuado contrasta con el valor inicial predeterminado dado a las variables de clase durante la preparación. Como se describió anteriormente, la máquina virtual asigna valores predeterminados basados ​​únicamente en el tipo de cada variable. Los valores iniciales adecuados, por el contrario, se basan en un plan maestro conocido solo por el programador. En el código Java, se especifica un valor inicial adecuado mediante un inicializador variable de clase o un inicializador estático.

Entonces sabemos que una vez que MyClassse carga e inicializa, se creará el objeto de la clase complementaria.

pero, ¿qué haría que se cargara JVM MyClass?

La especificación Java Virtual Machine brinda flexibilidad a las implementaciones en el tiempo de carga y vinculación de clase e interfaz, pero define estrictamente el tiempo de inicialización. Todas las implementaciones deben inicializar cada clase e interfaz en su primer uso activo. Un uso activo de una clase es:

  1. La invocación de un constructor en una nueva instancia de la clase.

  2. La creación de una matriz que tiene la clase como su tipo de elemento

  3. La invocación de un método declarado por la clase (no heredado de una superclase)

4 El uso o asignación de un campo declarado por la clase (no heredado de una superclase o super interfaz), excepto los campos que son estáticos y finales, y se inicializan mediante una expresión constante en tiempo de compilación

Entonces, según el 4to punto cuando lo haga MyClass.foo()desde kotlin o MyClass.Companion.foo()en este punto MyClass, estará cargado y listo. (Probablemente mucho antes)

Tenga en cuenta que en este momento no MyClassexiste ningún objeto de existencia, es decir, no hemos utilizado expresión MyClass().

¿Significa esto que los staticcampos permanecerán en la memoria mientras la aplicación se esté ejecutando?

Se pueden recolectar basura si el tipo de declaración se descarga, en nuestro caso si JVM o ART (en Android) se descargan, MyClassentonces existe la posibilidad de que se recolecte basura.

JVM Spec tiene lo siguiente que decir sobre la descarga de clases

Una implementación del lenguaje de programación Java puede descargar clases.

Una clase o interfaz puede descargarse si y solo si su recolector de clase definitoria puede ser reclamado por el recolector de basura como se discutió en §12.6.

Las clases e interfaces cargadas por el cargador de arranque no se pueden descargar.

En la práctica, la descarga de clases casi (dije casi) nunca ocurre, por lo que sí, los objetos complementarios permanecerán en la memoria durante el ciclo de vida de la aplicación .

mightyWOZ
fuente