Коли я створюю об'єкт, свіжа пам'ять виділяється і на поля екземпляра, і на методи, або лише на поля екземпляра


14

У мене такий клас

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);

}
}

Тепер я створюю два об'єкти типу Student наступним чином

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

Тепер для різних примірників виділено два різних набори пам'яті. Тепер моє запитання - чи виділяється пам'ять для методів ( setResultі displayResult) двічі чи один раз?

Будь ласка, подивіться наступну рисунок і чи можете ви допомогти мені сказати, яка цифра дає правильну інформацію.

введіть тут опис зображення


1
Обмін дослідженнями допомагає всім . Розкажіть, що ви пробували і чому це не відповідало вашим потребам. Це свідчить про те, що ви знайшли час, щоб спробувати допомогти собі, це позбавляє нас від повторення очевидних відповідей, а найбільше це допомагає вам отримати більш конкретну та релевантну відповідь. Також дивіться Як просити
gnat

3
Я вивчаю Java ... і в усіх матеріалах вони просто кажуть, що кожного разу, коли ми створюємо об'єкт, свіжа пам'ять виділяється на всі поля екземпляра. ні
Harish_N

Відповіді:


13

Код методів є частиною Class(більш коротко Class<Student>) і завантажується в пам'ять при першому завантаженні класу.

Однак, при виконанні будь-якого методу використовується додаткова пам'ять для розподілу пам'яті параметрам, локальним змінним, тимчасовим результатам вираження, значенням повернення тощо. Але така пам'ять виділяється в стеку (пам'ять, яка використовується при створенні нового екземпляра, виділяється в купі .

Згідно з вашим запитанням, зараз повинно бути зрозуміло, що цифра B правильна (хоча вона не відображає те, що відбувається, коли ви насправді викликаєте метод).


Добре. Я зараз на 90% зрозумілий .... Але невеликий сумнів. Припустимо, якщо я створю 10 об'єктів типу Student, тоді методам, присутнім у класі Student, виділяється лише 1 набір свіжої пам’яті, тоді як 10 наборів свіжої пам’яті є виділено для зберігання змінних екземплярів для 10 об'єктів. Я прав?
Harish_N

Правильно. Подумайте, що пам'ять займає не лише властивості, але і невеликий накладний зв'язок, пов'язаний із самим екземпляром (екземпляр класу без властивостей використовуватиме більше 0 байт пам'яті).
SJuan76

Ще одне ... Я задав питання, маючи на увазі Java .... Чи те ж саме відбувається і в Java .....
Harish_N

Специфікація мови Java нічого не говорить про те, скільки пам'яті виділяється, коли і з якою метою. Це залишається виконавцю, і кожен виконавець може вибрати інше.
Йорг W Міттаг

6

Поля екземплярів (включаючи резервні поля власності) отримують N-копії для N-об'єктів.

Статичні поля отримують одну копію на клас.

Методи - це блоки байт-коду (або після JIT, блоки нативних інструкцій), які є частиною програмного "зображення" або виконуваного сегмента коду. Методи вже є частиною зображення програми, оскільки вона сидить на диску. Після завантаження зображення ОС (або CLR), є одна спільна копія коду методу.

Вони взагалі не є частиною розподілу "купи" або розподілу часу, за винятком випадків, коли ви можете використовувати компілятор, що використовується в обробці, для складання нових методів на ходу. Методи не «виділяються» як об'єкти і не «виділяються» щодо створення об’єкта. Вони просто існують як частина програми до того, як один об'єкт коли-небудь інстанціюється. Навіть лямбда / делегати не виділяються з льоту. Компілятор створює класи на вимогу для реалізації цих інших, здавалося б, динамічних об'єктів коду, і вони також існують як частина зображення байт-коду на диску.

ОНОВЛЕННЯ за коментарі:

Стандарт JVM має таке значення:

2.5.4. Область методу

У віртуальної машини Java є область методів, яка поділяється між усіма потоками віртуальної машини Java. Область методу аналогічна області зберігання для складеного коду звичайної мови або аналогічна сегменту "текст" в процесі операційної системи. Він зберігає структури за класом, такі як постійний пул часу виконання, дані про поле та методи, а також код для методів та конструкторів, включаючи спеціальні методи (§2.9), що застосовуються при ініціалізації класів та екземплярів та ініціалізації інтерфейсу.

Область методу створюється при запуску віртуальної машини. Хоча область методу логічно є частиною купи, прості реалізації можуть вирішити не збирати сміття чи ущільнювати його. Ця версія специфікації Java Virtual Machine не передбачає розташування області методу або політики, що використовуються для управління компільованим кодом. Область методу може мати фіксований розмір або може бути розширена, як вимагає обчислення, і може бути скорочена, якщо більша область методу стає непотрібною. Пам'ять для області методу не повинна бути суміжною.

Тож зрозуміло, що (1) так, специфіка не диктує, як це робиться, але (2) аналогічно області зберігання для складеного коду звичайної мови, тобто. текстовий сегмент. Це я і роблю.


Те, що ви говорите, має сенс, але чи це насправді гарантоване JLS? Зазвичай JLS надає виконавцям багато можливостей у таких питаннях.
Йорг W Міттаг

Не впевнений у цьому пункті, @ JörgWMittag. Можливо ти правий. Я намагався зробити «новий T ()» не виділяє новий примірник методу. Що стосується специфіки JVM, то завантажувачі класів дійсно зберігають байтовий код у купі, і, мабуть, можливі сценарії, коли самі класи описуються і навіть збирають сміття. Але це деталізація впровадження під час виконання, і, концептуально, купа, про яку я говорю, - це купа "користувача". Клас та методи не вважаються даними у звичайному контексті користувача. Але оскільки ми також можемо керувати завантажувачем класів з userland, я думаю, я не знаю.
codenheim

JLS взагалі не говорить про купу, чи не так? Цілком законно реалізовувати Java з динамічним стеком і без купи замість обмеженого стека фіксованого розміру та динамічної купи. JLS також нічого не говорить про JVM, це цілком справедливо для реалізації Java без JVM.
Jörg W Mittag

Ви посилаєтесь на JLS, але я кажу про JVM. Стандарт JVM, безумовно, обговорює купу. Ви повинні надати змінну область застосування / термін служби, яка уникає локальної області дії стека. Щодо того, що теоретично можливо, я вважаю за краще думати з точки зору "відомих реалізацій". Я впевнений, що реалізувати повний JVM без купи примітивів - це важка або навіть неможлива робота, оскільки JVM не є чистою стековою машиною. Я розумію машини Forth та інших чистих архітектурних стеків, що це можливо, якщо існуватиме примітив для випадкового змінного доступу, але я просто не бачив цього.
codenheim

@ JörgWMittag - Я відповів на відповідь щось, що може зацікавити нашу дискусію. Справа в тому, що я проводив аналогію з традиційним кодом або текстовим сегментом у звичайних системах виконання.
codenheim

-4

Об'єкт, виділений у heap memory.when об'єкт виділяється слотом для всієї змінної екземпляра, створюється і знищується, коли об'єкт знищується. Значення екземпляра також виділяється в heap memory. І локальна змінна створюється в стеці в той момент, коли метод називають.


1
Здається, це просто повторює інформацію, яка міститься в попередніх відповідях.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.