Uruchomiłem visualvm i zauważyłem, że w pamięci zostają jakieś elementy JavaFX. W ogóle na początku podejrzewam framework graficzny, bo on musi dużo rzeczy przechowywać i wystarczy przegapić jakiś jeden dispose, żeby zapychał pamięć. Na Swingu jest podobnie.
Potem patrzyłem, kiedy te elementy powstają. Sprawdzałem w kolejnych dumpach, jakie obiekty się pojawiają, a jakie zostają, choć powinny znikać. Zwróciłem uwagę na ScreenMainRightController. Po wpisaniu w visualvm w widoku Classes, w filtrze: RightCon - widziałem, ile tych kontrolerów jest utworzonych. I widziałem, że ich liczba rośnie. Dla odmiany liczba kontrolerów ScreenMainController była ciągle równa 1.
Należało więc przyjrzeć się miejscu, gdzie powstaje ten Right. No i tam tworzony jest taki obiekt (przez new), do którego referencja natychmiast jest tracona. Czyli bałaganiarstwo, ale niegroźne. Bo przecież element bez referencji natychmiast zostanie zgarnięty przez GC. Chyba że konstruktor gdzieś zostawia ślad po sobie, tworzy jakiś wyciek. No dobra, Right nie ma w ogóle konstruktora, czyli spokój. Ale zaraz, przecież on dziedziczy konstruktor po AnchorPane. No to pewnie AnchorPane (komponent JavaFX), gdzieś się sam rejestruje. Podebugowałem trochę JavaFX, dzięki Intellijejowi, który ładnie dekompiluje kod. I znalazłem takie miejsce: w Node.java:
pickOnBounds = new SimpleBooleanProperty(this, "pickOnBounds");
Tutaj zachowuje się referencja do naszego kontrolera. Nigdy nie robimy na nim close()
, więc zostaje w pamięci do końca. W zasadzie trudno zrobić close
, jak taka metoda nie istnieje :)
Rzeczywiście, visualvm wskazywał te miejsca w widoku: ScreenMainRightController, Show In Instances View, Show Nearest GC Root. Były tam wymienione i Node i SimpleBooleanProperty. Czyli wszystko się zgadza.
Pozostaje więc zadbać o to, by nie tworzyć 2 kontrolerów, a 1. Powinno się uspokoić. ScreenManager.loadFxml - tu gubiony jest stary kontroler i tworzony od razu nowy. Usuwam więc parametr controller i usuwam ten argument ze wszystkich wywołań. Niestety, to nie wystarcza.
Patrzę jeszcze na akcję zamknięcia projektu, closeProject(). Nie widzę tu żadnego zamknięcia okien. A przy otwieraniu projektu robisz ciągle FXMLLoader.load. Coś tu jest nie tak, ale nie powiem co, bo pierwszy raz oglądam aplikację JavaFX.