( BaT | 2014. 07. 19., szo – 18:03 )

Kezdjük a legegyszerűbb esettel. Körkörös hivatkozás, finalizer hivatkozik a másik objektumra, ha a másik már nem elérhető vagy netán garbage lenne a helyén, akkor azt jutalmazzuk assertion errorral: http://pastebin.com/3EQ9KNmh

Ahogy azt várjuk, a program soha nem száll el, fut egy darabig, majd jön a GC és szépen felszabadítja az objektumokat, majd megint fut egy darabig és így tovább.

Egy picit bonyolultabb eset, tegyük fel hogy mindig a kisebb indexű finalizerjét akarjuk előbb futtatni. Csak hogy lássunk ilyet is, most direkt el fogom rontani: http://pastebin.com/DMWkJzx1

A kimenet valami ilyesmi:


................ ... ...........B(629)#finalize calling other#finalize
	B(628)#finalize finalizer finished
 finalizer finished
B(376)#finalize finalizer finished
B(375)#finalize calling other#finalize
	B(374)#finalize finalizer finished
 finalizer finished
B(374)#finalize
java.lang.AssertionError
	at finalizerdemo.B.finalizerAssert(B.java:39)
	at finalizerdemo.B.finalize(B.java:22)
	at java.lang.System$2.invokeFinalize(System.java:1267)
	at java.lang.ref.Finalizer.runFinalizer(Finalizer.java:98)
	at java.lang.ref.Finalizer.access$100(Finalizer.java:34)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:210)

A lényeg, hogy attól, hogy kézzel ráhívsz a finalize-re, még a FinalizerThread is rá fog hívni. Ezért nem ajánlott kézzel hívni a finalize-t, nem véletlenül protected. A megoldás egyszerű, kell egy flag ami megmondja, hogy lefutott-e már a kérdéses kód. Most megvalósítottam ehhez a Closeable interfészt is, de az remélem látszik, hogy ez semmit nem befolyásol: http://pastebin.com/BQXWGsTg

Innentől kezdve nem tudok olyan esetet kitalálni, amit ne lehetne megoldani, olyan nem lesz hogy egy referencia már nem él, azt pedig lehet workaroundolni, hogy az esetleges erőforrás felszabadítások mikor, milyen sorrendben fussanak le.