Hier noch einmal der genaue Ablauf:
- Zunächst prüft der Garbage Collector, ob es noch Verweise auf das Objekt gibt.
Wenn es keine Verweise mehr gibt, hängt das weitere Vorgehen davon ab,
ob die zugehörige Klasse einen Finalisierer besitzt. Wenn sie keinen
Finalisierer besitzt, wird das Objekt entfernt, und der Speicher steht sofort wieder zur weiteren Nutzung bereit.
- Falls das Objekt dagegen über einen Finalisierer verfügt, wird er
aufgerufen.
- Nachdem finalize() ausgeführt wurde, wird noch einmal
geprüft, ob es keine Verweise auf das Exemplar mehr gibt, bevor der Speicher
freigegeben wird. Diese Überprüfung ist notwendig, da prinzipiell
im Finalisierer wieder ein Verweis auf das Exemplar erzeugt werden kann.
Wenn die Prüfung ergibt, dass kein neuer Verweis erzeugt wurde, dann wird
der Speicher freigegeben. Wurde dagegen ein neuer Verweis auf das Exemplar angelegt, wird das Objekt sofort entfernt, wenn es zu einem späteren Zeitpunkt keine Verweise mehr gibt. Der Finalisierer wird hierbei kein zweites Mal aufgerufen.
Bezüglich der Finalisierung gelten folgende Regeln:
- Es besteht keine Garantie dafür, dass finalize()
aufgerufen wird. Möglicherweise wird der Garbage Collector während der Laufzeit des Interpreters gar nicht aufgerufen, so dass noch belegte Ressourcen vom Betriebssystem
freigegeben werden. Für Abschlussaktionen, die garantiert ausgeführt werden sollen, muss auf Referenzklassen oder Shutdown-Routinen zurückgegriffen werden.
- Der Finalisierer eines Exemplars wird höchstens einmal aufgerufen.
- Falls bei der Ausführung von finalize() eine Exception auftritt, die
nicht in der Methode selbst abgefangen wird, dann wird die Ausführung des Programms nicht abgebrochen, sondern die Exception wird ignoriert.
- Da der Garbage Collector asynchron läuft, können keine Annahmen über den Aufrufzeitpunkt von finalize() gemacht werden.
- Es können keine Annahmen darüber gemacht werden, in welcher Reihenfolge Objekte entfernt werden.
Seit der Version 1.1 besteht die Möglichkeit, mit dem Aufruf
System.runFinalization();
noch ausstehende Finalisierungen sofort zu starten. Alternativ kann mit
System.runFinalizersOnExit(true);
die Ausführung ausstehender finalize()-Methoden am Ende der Laufzeit der Virtual Machine erzwungen werden.