AFAIK, la specifica JVM (scritta in inglese) non menziona quando esattamente un oggetto (o un valore) dovrebbe essere cancellato e lo lascia all'implementazione (anche per R5RS ). In qualche modo richiede o suggerisce un garbage collector ma lascia i dettagli all'implementazione. E allo stesso modo per le specifiche Java.
Ricorda che i linguaggi di programmazione sono specifiche (di sintassi , semantica , ecc ...), non implementazioni di software. Un linguaggio come Java (o la sua JVM) ha molte implementazioni. Le sue specifiche sono pubblicate , scaricabili (in modo da poterle studiare) e scritte in inglese. §2.5.3 L'heap delle specifiche JVM menziona un garbage collector:
L'archiviazione dell'heap per gli oggetti viene recuperata da un sistema di gestione dell'archiviazione automatica (noto come garbage collector); gli oggetti non vengono mai deallocati esplicitamente. La Java Virtual Machine non assume alcun tipo particolare di sistema di gestione dello storage automatico
(l'enfasi è mia; la finalizzazione BTW è menzionata nel §12.6 delle specifiche Java e un modello di memoria è nel §17.4 delle specifiche Java)
Quindi (in Java) non dovresti preoccuparti quando un oggetto viene eliminato e potresti codificare come se non dovesse accadere (ragionando in un'astrazione in cui lo ignori). Ovviamente devi preoccuparti del consumo di memoria e del set di oggetti viventi, che è una domanda diversa . In molti semplici casi (pensate a un programma "ciao mondo") siete in grado di dimostrare, o per convincervi, che la memoria allocata è piuttosto piccola (ad esempio meno di un gigabyte), e quindi non vi interessa affatto cancellazione di singoli oggetti. In più casi, puoi convincerti che gli oggetti viventi(o quelli raggiungibili, che è un superset - più facile da ragionare - di quelli viventi) non superano mai un limite ragionevole (e quindi fai affidamento su GC, ma non ti importa come e quando avviene la raccolta dei rifiuti). Leggi la complessità dello spazio .
Immagino che su diverse implementazioni JVM che eseguono un programma Java di breve durata come un ciao mondo, il garbage collector non sia affatto attivato e non si verifichi alcuna eliminazione. AFAIU, un simile comportamento è conforme alle numerose specifiche Java.
La maggior parte delle implementazioni JVM utilizzano tecniche di copia generazionale (almeno per la maggior parte degli oggetti Java, quelli che non usano la finalizzazione o riferimenti deboli ; la finalizzazione non è garantita in breve tempo e potrebbe essere posticipata, quindi è solo una funzione utile che il codice non dovrebbe dipende molto da) in cui la nozione di cancellare un singolo oggetto non ha alcun senso (dal momento che un grande blocco di memoria contenente zone di memoria per molti oggetti, forse diversi megabyte contemporaneamente, viene rilasciato contemporaneamente).
Se la specifica JVM richiedesse che ogni oggetto venisse cancellato il più presto possibile (o semplicemente ponesse ulteriori vincoli alla cancellazione dell'oggetto), sarebbero vietate tecniche GC generazionali efficienti e i progettisti di Java e della JVM sarebbero stati saggi nel evitarlo.
A proposito, potrebbe essere possibile che una JVM ingenua che non cancella mai oggetti e non rilasci memoria possa essere conforme alle specifiche (la lettera, non lo spirito) e certamente è in grado di eseguire un ciao mondo in pratica (nota che la maggior parte i programmi Java piccoli e di breve durata probabilmente non allocano più di qualche gigabyte di memoria). Naturalmente una JVM del genere non merita di essere menzionata ed è solo una cosa giocattolo (come questa implementazione di malloc
per C). Per ulteriori informazioni, consultare Epsilon NoOp GC . Le JVM reali sono software molto complessi e mescolano diverse tecniche di raccolta dei rifiuti.
Inoltre, Java non è lo stesso di JVM e le implementazioni Java sono in esecuzione senza JVM (ad es. Compilatori Java anticipati , runtime Android ). In alcuni casi (principalmente accademici), potresti immaginare (le cosiddette tecniche di "raccolta dei dati inutili") che un programma Java non alloca o elimina in fase di esecuzione (ad esempio perché il compilatore di ottimizzazione è stato abbastanza intelligente da utilizzare solo il stack di chiamate e variabili automatiche ).
Perché gli oggetti Java non vengono eliminati immediatamente dopo che non sono più referenziati?
Perché le specifiche Java e JVM non lo richiedono.
Leggi il manuale GC per ulteriori informazioni (e le specifiche JVM ). Si noti che essere vivo (o utile per il calcolo futuro) per un oggetto è una proprietà dell'intero programma (non modulare).
Objective-C favorisce un approccio di conteggio dei riferimenti alla gestione della memoria . E che ha anche insidie (ad esempio, l'Objective-C programmatore deve preoccuparsi di riferimenti circolari da esplicitando riferimenti deboli, ma una JVM gestisce riferimenti circolari bene in pratica senza richiedere l'attenzione da parte del programmatore Java).
Non esiste Silver Bullet nella programmazione e nella programmazione del linguaggio di programmazione (sii consapevole del problema Halting ; essere un oggetto vivente utile è ineccepibile in generale).
Puoi anche leggere SICP , Pragmatica del linguaggio di programmazione , Dragon Book , Lisp in piccoli pezzi e sistemi operativi: tre pezzi facili . Non si tratta di Java, ma apriranno la tua mente e dovrebbero aiutare a capire cosa dovrebbe fare una JVM e come potrebbe praticamente funzionare (con altri pezzi) sul tuo computer. Potresti anche dedicare molti mesi (o diversi anni) allo studio del complesso codice sorgente delle implementazioni JVM open source esistenti (come OpenJDK , che ha diversi milioni di righe di codice sorgente).