arrowman napisał(a)
Ale nie ma nic natywnego w JAVA do usuwania obiektu z pamięci? Nic, tak w ogóle?
W Javie w ogóle prawie nic nie ma natywnego. :)
Jak sobie pisałem gierkę w C# to mi to ułatwiało wiele spraw. Tutaj musiałbym za każdym razem np. usuwania pocisku wywalić go tylko z listy rysowanych elementów (no i kolizji itp.) i czekać aż łaskawie Szanowny Pan GC zechce sobie to usunąć
Przydział pamięci jest poza operacją na dysku najwolniejszą operacją jaką wykonuje JVM. Należy każdy new traktować pod względem wydajności podobnie jak czytanie z pliku - to znacznie ułatwi projektowanie czegokolwiek. Poza tym pozostawianie "niepotrzebnych" referencji, albo jest celowe, albo jest skutkiem błędu. Typowym przykładem jest zdejmowanie ze stosu referencji i nie wyczyszczenie ze stosu miejsca po niej - jednak czasem może to być celowe pozostawienie jako specyficzny rodzaj cache.
Bo zauważyłem, że jak mam 2 obiekty, do których są usunięte referencje, ale one mają do siebie referencje to GC nie usunie ich...
Bo usunie dopiero wtedy kiedy będzie brakowało wolnej pamięci w taki sposób, że JVM będzie musiało rozszerzyć swoją pamięć, przez pobranie kolejnej porcji z systemu. Wtedy dopiero obiekty będą masowo zwalniane, a wolne miejsce defragmentowane. To właśnie ta ostatnia operacja powoduje, że odśmiecanie jest bardziej efektywne, kiedy na raz da się zwolnić dużo. Jeżeli po każdej utracie referencji śmieciarz miałby odzyskiwać tę pamięć, to prowadziłoby to do takiej fragmentacji RAMu JVM, że w pewnym momencie i tak trzeba by było przeprowadzić bardzo kosztowną czasowo defragmentację. Efektywniej więc robić ją wtedy kiedy jest dużo obiektów do zwolnienia na raz.
Objawia się to tak, że zmniejsza się nieustannie "wolna" ilość pamięci i kiedy dojdzie ona do zera, to nagle odzyskuje się kilka do kilkudziesięciu MB na raz, następnie proces powtarza się. Oczywiście w sytuacji kiedy średnie użycie pamięci wciąż jest stałe. Kiedy rośnie, to JVM podwyższa pamięć przez zabranie jej systemowi i cały proces powtarza się na wyższym poziomie zużycia.
W C# robiłem sobie z pociskiem dispose() i grało:-) Żadnego zamiatania pod dywan. A jak pocisków są miliony? I potem miliony odłamków z tych milionów?
Polecenie new dlatego jest dość wolne, że właśnie kiedy śmieciarz odkryje dużą potrzebę przydziałów, a zupełnie nieużywanej pamięci jest za mało, to zaczyna zajmować się odśmiecaniem. Po prostu nie przejmuj się w ogóle nieużywanymi zasobami. Profiler pokaże, że jest to problem tylko jeżeli spore spowolnienia będą wyskakiwać cały czas w zupełnie losowych miejscach kodu. Ale jest to mało prawdopodobne.