JVM-Finalisierung erreichbarer Objekte in Java 8: Eine Untersuchung
Trotz der Einhaltung von Best Practices, die von der Verwendung von finalize() abraten, a Das jüngste Upgrade von Java 7 auf Java 8 hat ein unerwartetes Problem ans Licht gebracht. In diesem Szenario werden Objekte, die vom Stapel des aktuellen Threads immer noch stark erreichbar sind, einer Finalisierung in der Java 8-Laufzeit unterzogen.
Code und Ausnahme verstehen
Die Bei dem betreffenden Code handelt es sich um eine benutzerdefinierte MIME-Bibliothek, bei der die MIMEBodyPart-Klasse HTTPMessage erweitert. HTTPMessage implementiert eine finalize()-Methode, die versucht, den zugehörigen Eingabestream zu schließen, was zu einer Ausnahme führt, wenn der Stream während eines aktiven writePart()-Vorgangs bereits geschlossen ist.
Untersuchung der Ursache
Verwundert über die unerwartete Finalisierung befassten sich die Entwickler eingehender mit dem Code und dem JVM-Verhalten. Es wurde festgestellt, dass das MIMEBodyPart-Objekt tatsächlich vom Stapel des aktuellen Threads aus erreichbar war und daher nicht hätte finalisiert werden dürfen.
Hypothese der Möglichkeit der Unerreichbarkeit
Trotzdem Aufgrund der scheinbaren Erreichbarkeit des Objekts wurde die Theorie aufgestellt, dass die Java Virtual Machine (JVM) es auch dann noch als nicht erreichbar wahrnehmen könnte wird im nachfolgenden Code nicht explizit referenziert. Dieses Konzept der „Unerreichbarkeit“ erstreckt sich sogar auf aktive Methodenaufrufe auf dem Stapel.
Beispiel zur Demonstration der Unerreichbarkeit
Um dieses Verhalten zu veranschaulichen, wurde ein vereinfachtes Codebeispiel vorgestellt:
class FinalizeThis { @Override protected void finalize() { System.out.println("finalized!"); } void loop() { System.out.println("loop() called"); for (int i = 0; i < 1,000,000,000; i++) { if (i % 1,000,000 == 0) System.gc(); } System.out.println("loop() returns"); } public static void main(String[] args) { new FinalizeThis().loop(); } }
In diesem Beispiel enthält die Methode loop() eine umfangreiche Schleife, die regelmäßig die Speicherbereinigung auslöst. Obwohl die Schleifenmethode aktiv eine Instanzmethode des FinalizeThis-Objekts aufruft, wird das Objekt von der JVM finalisiert und aufgrund seiner scheinbaren Unerreichbarkeit in den Garbage Collection-Speicher überführt.
Anwenden der Hypothese auf das Originalszenario
Es wurde vermutet, dass sich eine ähnliche Situation im Fall des MIMEBodyPart-Objekts entwickeln könnte. Wenn es in einer lokalen Variablen ohne nachfolgende Referenzen gespeichert wurde, könnte es nicht mehr erreichbar und anfällig für die Finalisierung sein.
Aktualisierungen und zusätzliche Beobachtungen
Durch weitere Tests und Analysen, Es stellte sich heraus, dass der JIT-Compiler bei diesem Verhalten eine Rolle spielte. Durch das Erzwingen einer JIT-Kompilierung von Methoden vor der Ausführung (Option -Xcomp) trat das Problem einer vorzeitigen Finalisierung erneut auf. Dies deutet darauf hin, dass der anfängliche Mangel an Finalisierung im vereinfachten Beispiel eher auf die Interpretation als auf die Kompilierung zurückzuführen war, die eine aggressivere Erreichbarkeitsanalyse durchführt.
Schlussfolgerung
Während die Einzelheiten des Problems je nach der genauen Codestruktur und Ausführungsumgebung variieren können, ist das zugrunde liegende Konzept einer möglichen Finalisierung auch für erreichbare Objekte aufgrund der wahrgenommenen Nichterreichbarkeit bemerkenswert. Es unterstreicht, wie wichtig es ist, die Erreichbarkeit von Objekten und die möglichen Konsequenzen von Finalisierungsaufrufen für aktive Objekte zu verstehen.
Das obige ist der detaillierte Inhalt vonWarum werden erreichbare Java-Objekte in Java 8 finalisiert, obwohl Best Practices von „finalize()' abraten?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!