AFAIK, la especificación JVM (escrita en inglés) no menciona cuándo se debe eliminar exactamente un objeto (o un valor), y lo deja a la implementación (del mismo modo para R5RS ). De alguna manera requiere o sugiere un recolector de basura, pero deja los detalles para la implementación. Y del mismo modo para la especificación Java.
Recuerde que los lenguajes de programación son especificaciones (de sintaxis , semántica , etc.), no implementaciones de software. Un lenguaje como Java (o su JVM) tiene muchas implementaciones. Su especificación es publicada , descargable (para que pueda estudiarla) y escrita en inglés. §2.5.3 El montón de la especificación JVM menciona un recolector de basura:
El almacenamiento de almacenamiento dinámico para objetos es reclamado por un sistema de gestión de almacenamiento automático (conocido como recolector de basura); Los objetos nunca se desasignan explícitamente. La máquina virtual Java no asume ningún tipo particular de sistema de gestión de almacenamiento automático
(el énfasis es mío; la finalización de BTW se menciona en §12.6 de la especificación de Java, y un modelo de memoria está en §17.4 de la especificación de Java)
Entonces (en Java) no debería importarle cuando un objeto se elimina , y podría codificar como si no sucediera (razonando en una abstracción donde ignora eso). Por supuesto, hay que preocuparse por el consumo de memoria y el conjunto de objetos que viven, que es una diferente pregunta. En varios casos simples (piense en un programa de "hola mundo") puede probar, o convencerse, de que la memoria asignada es bastante pequeña (por ejemplo, menos de un gigabyte), y luego no le importa en absoluto eliminación de objetos individuales . En más casos, puedes convencerte de que los objetos vivos(o alcanzables, que es un superconjunto, más fácil de razonar sobre los vivos) nunca excede un límite razonable (y luego confía en GC, pero no le importa cómo y cuándo ocurre la recolección de basura). Lea sobre la complejidad del espacio .
Supongo que en varias implementaciones de JVM que ejecutan un programa Java de corta duración como hello world, el recolector de basura no se activa en absoluto y no se produce ninguna eliminación. AFAIU, tal comportamiento se ajusta a las numerosas especificaciones de Java.
La mayoría de las implementaciones de JVM usan técnicas de copia generacional (al menos para la mayoría de los objetos Java, aquellos que no usan finalización o referencias débiles ; y no se garantiza que la finalización suceda en poco tiempo y podría posponerse, por lo que es solo una característica útil que su código no debería dependerá mucho de ello) en el que la noción de eliminar un objeto individual no tiene ningún sentido (ya que un gran bloque de memoria -que contiene zonas de memoria para muchos objetos-, quizás varios megabytes a la vez, se libera a la vez).
Si la especificación JVM requiere que cada objeto se elimine exactamente lo antes posible (o simplemente imponga más restricciones a la eliminación de objetos), se prohibirían las técnicas de GC generacionales eficientes, y los diseñadores de Java y de la JVM han sido sabios al evitar eso.
Por cierto, podría ser posible que una JVM ingenua que nunca elimina objetos y no libera memoria se ajuste a las especificaciones (la letra, no el espíritu) y ciertamente pueda ejecutar una cosa de hola mundo en la práctica (tenga en cuenta que la mayoría los programas Java pequeños y de corta duración probablemente no asignen más de unos pocos gigabytes de memoria). Por supuesto, no vale la pena mencionar tal JVM y es solo una cosa de juguete (como es esta implementación de malloc
C). Vea el Epsilon NoOp GC para más información. Las JVM de la vida real son piezas de software muy complejas y combinan varias técnicas de recolección de basura.
Además, Java no es lo mismo que JVM, y tiene implementaciones de Java ejecutándose sin JVM (por ejemplo , compiladores Java anticipados , tiempo de ejecución de Android ). En algunos casos (en su mayoría académicos), puede imaginarse (llamadas técnicas de "recolección de basura en tiempo de compilación") que un programa Java no asigna o elimina en tiempo de ejecución (por ejemplo, porque el compilador de optimización ha sido lo suficientemente inteligente como para usar solo el pila de llamadas y variables automáticas ).
¿Por qué no se eliminan los objetos Java inmediatamente después de que ya no se hace referencia a ellos?
Porque las especificaciones Java y JVM no requieren eso.
Lea el manual de GC para obtener más información (y la especificación JVM ). Observe que estar vivo (o útil para el cálculo futuro) de un objeto es una propiedad de todo el programa (no modular).
Objective-C favorece un enfoque de conteo de referencia para la gestión de la memoria . Y que también tiene trampas (por ejemplo, el Objective-C programador tiene que preocuparse por las referencias circulares por explicitar referencias débiles, pero una JVM maneja referencias circulares muy bien en la práctica sin necesidad de atención por parte del programador de Java).
No hay Silver Bullet en la programación y el diseño del lenguaje de programación (tenga en cuenta el problema de detención ; ser un objeto vivo útil es indecidible en general).
También puede leer SICP , Pragmática del lenguaje de programación , El libro del dragón , Lisp en piezas pequeñas y Sistemas operativos: tres piezas fáciles . No se trata de Java, pero le abrirán la mente y deberían ayudarlo a comprender qué debe hacer una JVM y cómo podría funcionar prácticamente (con otras piezas) en su computadora. También podría pasar muchos meses (o varios años) estudiando el código fuente complejo de implementaciones JVM de código abierto existentes (como OpenJDK , que tiene varios millones de líneas de código fuente).