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 static
referencia a la clase compañera, la pregunta se reduce al tiempo de vida de los static
campos en jvm class
y 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 class
objeto 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 static
se 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 MyClass
se 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:
La invocación de un constructor en una nueva instancia de la clase.
La creación de una matriz que tiene la clase como su tipo de elemento
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 MyClass
existe ningún objeto de existencia, es decir, no hemos utilizado expresión MyClass()
.
¿Significa esto que los static
campos 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, MyClass
entonces 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 .