2012-01-20 11 views
10

Zajmuję się problemami z pamięcią w mojej aplikacji i próbuję się skupić na zbieraniu śmieci. Jeśli mam następujący kod:W którym miejscu jest dokładnie dostępny obiekt do zbierania śmieci?

public void someMethod() { 
    MyObject myObject = new MyObject(); 
    myObject.doSomething(); //last use of myObject in this scope 
    doAnotherThing(); 
    andEvenMoreThings(); 
} 

Więc moje pytanie jest, będzie myObject być dostępny do zbierania śmieci po myObject.doSomething() który jest ostatnim korzystanie z tego obiektu lub po zakończeniu someMethod() gdzie chodzi poza zakresem? To znaczy. czy kolekcja śmieci jest na tyle sprytna, że ​​chociaż zmienna lokalna jest nadal w zasięgu, to nie będzie używana przez resztę kodu?

+1

Myślę, że używasz "dereferencji" w złym kontekście. – isah

+1

Tylko dlatego, że garbage collector widzi, że nie jest używane, nie oznacza, że ​​zdecyduje się go od razu uwolnić - nie powinieneś pisać kodu, który zależy od zachowania nieprzewidywalnego zdarzenia;) JEŚLI masz problemy z pamięcią wtedy prawdopodobnie przez pomyłkę zachowujesz odniesienia do czegoś :( – deanWombourne

+0

Hmm, dziękuję, taa, myślę, że masz rację, zaktualizuję tytuł do pytania: –

Odpowiedz

4

"Jeżeli chodzi poza zakresem"

public void someMethod() { 
    MyObject myObject = new MyObject(); 
    myObject.doSomething(); //last use of myObject in this scope 
    myObject = null; //Now available for gc 
    doAnotherThing(); 
    andEvenMoreThings(); 
} 
+0

stanie się to w linii 4, ponieważ jawnie dereferencji myObject = null; // Teraz dostępny dla gc –

+0

Tak, to jest poprawne.Nie ma to znaczenia, – Farmor

+1

w tym pytaniu, ale zakończy się po kręceniu klamra, ponieważ nie ma potrzeby dereferencji .. –

2

Po zasięgu lokalnym jest obecnie. jako obiekt może być ponownie użyty i może żyć w zasięgu lokalnym. to znaczy. jest oznaczony jako gc. ale nie faktycznie gc'ed.

2

Optymalizacja kodu zapewne zauważy gdzie ostatni wykorzystanie z myObject jest i udostępnić go do gromadzenia tam śmieci, jednak technicznie będzie dopóki zmienna nie odnosi się już do niej (o czym przypisane do czegoś innego) albo idzie poza zakresem.

+0

Nie sądzę, że jest to dozwolone przez JLS - a przynajmniej hotspot tego nie robi. .NET DOES faktycznie pozwala dokładnie to, co oznacza, że ​​mamy [GC.KeepAlive] (http://msdn.microsoft.com/en-us/library/system.gc.keepalive.aspx), aby uniknąć zbierania obiektów (np. efekty uboczne wcześniej niż byśmy chcieli. Przynajmniej na Jawie nigdy nie natknąłem się na żadną wzmiankę o tym, co by mnie zaskoczyło. – Voo

+0

Interesujące. Przez optymalizację kodu, masz na myśli wykonanie JVM, wykonanie GC czy kompilację kodu? –

4

Najlepszą rzeczą, jaką możesz zrobić, to wziąć swój kod w pętlę z opóźnieniem i podpiąć do niego profilera.

Jeśli używasz nowszej wersji Javy, wówczas JVisualVm jest standardem.

Jeśli jesteś na oknach i mają JAVA_HOME ustawiona

% JAVA_HOME%/bin/jvisualvm

Spowoduje to uruchomienie profilera i można zobaczyć, jakie przedmioty są gromadzone, a co nie jest . Moim zdaniem jest to istotna część bycia programistą i czerpanie radości ze znajdowania wycieków pamięci.

Nadzieja to pomaga

+0

+1 za poradę dla profilerów – helios

4

Btw w późniejszym Java 6, istnieje rodzaj escape analysis JVM gdzie można dowiedzieć się, że wystąpienie MyObject nie pozostawia sposób, więc może nawet umieścić go w całości na stosie i ci w ogóle nie będzie potrzebował żadnego GC.

3

Więc moje pytanie brzmi, czy MyObject być dostępny do zbierania śmieci po myObject.doSomething(), która jest ostatnim wykorzystanie tego obiektu lub po zakończeniu metody someMethod(), gdzie wychodzi z zakresu?

Były.

tj. czy kolekcja śmieci jest na tyle sprytna, że ​​chociaż zmienna lokalna jest nadal w zasięgu, to nie będzie używana przez resztę kodu?

Zasięg nie jest widoczny dla GC, który widzi tylko rejestry, stosy, zmienne globalne i odniesienia z bloków sterty do innych bloków sterty. Więc zakres nie ma znaczenia.

Powiązane problemy