Kiedy tworzę obiekt, nowa pamięć jest przydzielana zarówno do pól instancji, jak i do metod lub tylko do pól instancji

14

Mam następującą klasę

class Student{

int rollNumber;
int marks;

public void setResult(int rollNumber, int marks){

    this.rollNumber=rollNumber;
    this.marks=marks;   
}

public void displayResult(){

    System.out.println("Roll Number= "+this.rollNumber+"   Marks= "+this.marks);

}
}

Teraz tworzę dwa obiekty typu Student w następujący sposób

Student s1=new Student();
Student s2=new Student();

Teraz przydzielono dwa różne zestawy pamięci dla pól instancji. Teraz moje pytanie brzmi: czy pamięć jest przydzielana na metody ( setResulti displayResult) dwa razy czy raz?

Proszę zobaczyć poniższy rysunek i czy możesz mi pomóc powiedzieć, który rysunek zawiera prawidłowe informacje.

wprowadź opis zdjęcia tutaj

Harish_N
źródło
1
Udostępnianie badań pomaga wszystkim . Powiedz nam, co próbowałeś i dlaczego nie spełnia twoich potrzeb. To pokazuje, że poświęciłeś trochę czasu, aby spróbować sobie pomóc, oszczędza nam to powtarzania oczywistych odpowiedzi, a przede wszystkim pomaga uzyskać bardziej konkretną i odpowiednią odpowiedź. Zobacz także How to Ask
gnat
3
Uczę się java ... i we wszystkich materiałach mówią tylko, że za każdym razem, gdy tworzymy obiekt, nowa pamięć jest przydzielana do wszystkich pól instancji .. ale żaden z materiałów nie powiedział, czy nowa pamięć zostanie przydzielona dla metod, czy nie
Harish_N,

Odpowiedzi:

13

Kod metod jest częścią Class(bardziej zwięźle Class<Student>) i jest ładowany do pamięci, gdy klasa jest ładowana po raz pierwszy.

To powiedziawszy, kiedy wykonasz jakąkolwiek metodę, używana jest dodatkowa pamięć, aby przydzielić pamięć do parametrów, zmiennych lokalnych, wyników wyrażeń tymczasowych, wartości zwracanych i tak dalej. Ale taka pamięć jest przydzielana na stosie (pamięć używana podczas tworzenia nowej instancji jest przydzielana na stercie .

Zgodnie z twoim pytaniem, powinno być teraz jasne, że liczba B jest poprawna (chociaż nie odzwierciedla tego, co dzieje się, gdy faktycznie wywołujesz metodę).

SJuan76
źródło
Dobrze. Jestem teraz w 90% czysty .... Ale mam małe wątpliwości .. Załóżmy, że jeśli utworzę 10 obiektów typu Student, wówczas tylko 1 zestaw świeżej pamięci zostanie przydzielony do metod obecnych w klasie Student, podczas gdy 10 zestawów świeżej pamięci to przydzielone do przechowywania zmiennych instancji dla 10 obiektów. Mam rację?
Harish_N,
Dobrze. Pomyśl, że nie tylko właściwości zajmują pamięć, istnieje niewielki narzut związany z samą instancją (instancja klasy bez właściwości zużyje więcej niż 0 bajtów pamięci).
SJuan76
Jeszcze jedna rzecz ... Zadałem pytanie, mając na uwadze java ... Czy to samo dzieje się w java .....
Harish_N
Specyfikacja języka Java nie mówi nic o tym, ile pamięci jest przydzielane, kiedy i do jakiego celu. Pozostaje to implementatorowi, a każdy implementator może wybrać inaczej.
Jörg W Mittag
6

Pola instancji (w tym pola kopii właściwości) otrzymują N-kopii dla N-obiektów.

Pola statyczne otrzymują po jednej kopii na klasę.

Metody to bloki kodu bajtowego (lub po JIT bloki instrukcji natywnych), które są częścią „obrazu” programu lub segmentu kodu wykonywalnego. Metody są już częścią obrazu programu, ponieważ znajduje się on na dysku. Po załadowaniu obrazu przez system operacyjny (lub CLR) istnieje jedna wspólna kopia kodu metody.

Nie są one częścią alokacji „sterty” ani środowiska wykonawczego, z wyjątkiem przypadków, w których można użyć kompilatora hostowalnego do kompilacji nowych metod w locie. Metody nie są „przydzielane” jak obiekty i nie są „przydzielane” w stosunku do tworzenia obiektu. Istnieją jedynie jako część programu, zanim zostanie utworzony instancja jednego obiektu. Nawet lambdas / delegaci nie są przydzielani na bieżąco. Kompilator tworzy klasy na żądanie, aby zaimplementować te pozornie dynamiczne obiekty kodu, a także istnieją jako część obrazu kodu bajtowego na dysku.

AKTUALIZACJE dla komentarzy:

Standard JVM ma to do powiedzenia:

2.5.4 Obszar metody

Wirtualna maszyna Java ma obszar metod, który jest wspólny dla wszystkich wątków wirtualnej maszyny Java. Obszar metody jest analogiczny do obszaru przechowywania skompilowanego kodu konwencjonalnego języka lub analogiczny do segmentu „tekstowego” w procesie systemu operacyjnego. Przechowuje struktury dla poszczególnych klas, takie jak pula stałych w czasie wykonywania, dane pól i metod, a także kod metod i konstruktorów, w tym specjalne metody (§2.9) używane do inicjalizacji klas i instancji oraz inicjalizacji interfejsu.

Obszar metody jest tworzony podczas uruchamiania maszyny wirtualnej. Chociaż obszar metody jest logicznie częścią sterty, proste implementacje mogą zdecydować, że nie będzie go odśmiecać ani kompaktować. Ta wersja specyfikacji wirtualnej maszyny Java nie wymaga lokalizacji obszaru metody ani zasad używanych do zarządzania skompilowanym kodem. Obszar metody może mieć ustalony rozmiar lub może zostać rozszerzony zgodnie z wymaganiami obliczeń i może zostać skrócony, jeśli większy obszar metody stanie się niepotrzebny. Pamięć obszaru metody nie musi być ciągła.

Jest więc jasne, że (1) tak specyfikacja nie określa, jak to się robi, ale (2) jest analogiczna do obszaru przechowywania skompilowanego kodu konwencjonalnego języka, tj. segment tekstowy. Właśnie o to mi chodzi.

codenheim
źródło
To, co mówisz, ma sens, ale czy faktycznie jest to zagwarantowane przez JLS? Zwykle JLS daje implementatorom dużą swobodę w takich pytaniach.
Jörg W Mittag
Nie jestem pewien w tej kwestii, @ JörgWMittag. Możesz mieć rację. Chodzi mi o to, że „nowa T ()” nie przydziela nowej instancji metody. Jeśli chodzi o specyfikę JVM, moduły ładujące rzeczywiście przechowują kod bajtowy w stercie, i sądzę, że są możliwe scenariusze, w których same instancje są tworzone, a nawet zbierane śmieci. Ale jest to szczegół implementacji środowiska wykonawczego, a koncepcyjnie kupa, o której mówię, jest stertą „użytkownika”. Klasa i metody nie są uważane za dane w normalnym kontekście użytkownika. Ale ponieważ możemy również kontrolować moduł ładujący z przestrzeni użytkownika, wydaje mi się, że nie wiem.
codenheim
JLS w ogóle nie mówi o kupie, prawda? Implementacja Javy z dynamicznym stosem i bez stosu jest całkowicie legalna, zamiast ograniczonego stosu o stałej wielkości i stosu dynamicznego. JLS również nie mówi nic o JVM, jest całkowicie poprawne, aby zaimplementować Javę bez JVM.
Jörg W Mittag
Odwołujesz się do JLS, ale mówię o JVM. Standard JVM z pewnością omawia sterty. Musisz podać zmienny zakres / czas życia, który nie uwzględnia lokalnego zasięgu stosu. Jeśli chodzi o to, co jest teoretycznie możliwe, wolę myśleć w kategoriach „znanych wdrożeń”. Jestem prawie pewien, że wdrożenie pełnej JVM bez operacji podstawowej stosu jest trudnym, a nawet niemożliwym zadaniem, ponieważ JVM nie jest maszyną stosową. Rozumiem maszyny Fortha i inne architektury czystego stosu, że może być możliwe, jeśli istnieje prymitywny dostęp do zmiennych losowych, ale po prostu go nie widziałem.
codenheim
@ JörgWMittag - Do odpowiedzi dodałem coś, co może zainteresować naszą dyskusję. Chodzi o to, że rysowałem analogię do tradycyjnego segmentu kodu lub tekstu w tradycyjnych systemach wykonawczych.
codenheim
-4

obiekt alokowany w pamięci sterty. gdy obiekt jest alokowany, miejsce na wszystkie zmienne instancji jest tworzone i niszczone, gdy obiekt jest niszczony, więc zmienna instancji jest również alokowana w pamięci sterty, a zmienna lokalna jest tworzona na stosie w momencie, gdy są wywoływane metody.

Abhishek Tripathi
źródło
1
Wydaje się to po prostu powtarzać informacje zawarte we wcześniejszych odpowiedziach.