Khi tôi tạo một đối tượng, bộ nhớ mới được phân bổ cho cả các trường và phương thức hoặc chỉ cho các trường đối tượng


14

Tôi có một lớp học sau

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

}
}

Bây giờ tôi tạo hai đối tượng kiểu Sinh viên như sau

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

Bây giờ hai bộ bộ nhớ khác nhau được phân bổ cho các trường ví dụ. Bây giờ câu hỏi của tôi là liệu bộ nhớ được phân bổ cho các phương thức ( setResultdisplayResult) hai lần hay một lần?

Xin vui lòng xem hình dưới đây và bạn có thể giúp tôi nói hình nào cho thông tin chính xác.

nhập mô tả hình ảnh ở đây


1
Chia sẻ nghiên cứu của bạn giúp mọi người . Hãy cho chúng tôi những gì bạn đã cố gắng và tại sao nó không đáp ứng nhu cầu của bạn. Điều này chứng tỏ rằng bạn đã dành thời gian để cố gắng tự giúp mình, nó giúp chúng tôi tránh nhắc lại các câu trả lời rõ ràng và hầu hết nó giúp bạn có được câu trả lời cụ thể và phù hợp hơn. Xem thêm Cách hỏi
gnat

3
Tôi đang học java ... và trong tất cả các tài liệu họ chỉ nói rằng bất cứ khi nào chúng ta tạo một đối tượng, một bộ nhớ mới được phân bổ cho tất cả các trường đối tượng..nhưng, không có tài liệu nào nói liệu bộ nhớ mới sẽ được phân bổ cho các phương thức hay không
Harish_N

Câu trả lời:


13

Mã cho các phương thức là một phần của Class(chính xác hơn Class<Student>) và nó được tải vào bộ nhớ khi lớp được tải lần đầu tiên.

Điều đó nói rằng, khi bạn thực hiện bất kỳ phương thức nào, bộ nhớ bổ sung được sử dụng, để phân bổ bộ nhớ cho các tham số, biến cục bộ, kết quả biểu thức tạm thời, trả về giá trị, v.v. Nhưng bộ nhớ như vậy được phân bổ trong ngăn xếp (bộ nhớ được sử dụng khi tạo một thể hiện mới được phân bổ trong heap .

Theo câu hỏi của bạn, bây giờ cần phải rõ rằng hình B là chính xác (mặc dù nó không phản ánh những gì xảy ra khi bạn thực sự gọi phương thức).


Đồng ý. Bây giờ tôi đã rõ ràng 90% .... Nhưng một nghi ngờ nhỏ .. Giả sử nếu tôi tạo 10 đối tượng loại Sinh viên thì chỉ có 1 bộ nhớ mới được phân bổ cho các phương thức có trong lớp Sinh viên trong khi 10 bộ nhớ mới là Được phân bổ để lưu trữ các biến đối tượng cho 10 đối tượng..Am phải không?
Harish_N

Đúng. Hãy nghĩ rằng đó không chỉ là các thuộc tính chiếm bộ nhớ, có một chi phí nhỏ liên quan đến chính cá thể đó (một thể hiện của một lớp không có thuộc tính sẽ sử dụng nhiều hơn 0 byte bộ nhớ).
SJuan76

Một điều nữa ... Tôi đã đặt câu hỏi giữ java trong tâm trí .... Liệu điều tương tự có xảy ra trong java .....
Harish_N

Đặc tả ngôn ngữ Java không nói gì về lượng bộ nhớ được phân bổ khi nào và cho mục đích gì. Điều đó được để lại cho người thực hiện và mỗi người thực hiện có thể chọn khác nhau.
Jörg W Mittag

6

Các trường sơ thẩm (bao gồm các trường sao lưu thuộc tính) nhận bản sao N cho các đối tượng N.

Các trường tĩnh có được một bản sao duy nhất cho mỗi lớp.

Các phương thức là các khối mã byte (hoặc sau JIT, các khối lệnh gốc) là một phần của "hình ảnh" hoặc đoạn mã thực thi của chương trình. Các phương thức đã là một phần của hình ảnh chương trình khi nó nằm trên đĩa. Khi hình ảnh được tải bởi HĐH (hoặc CLR), sẽ có một bản sao được chia sẻ duy nhất của mã phương thức.

Chúng không phải là một phần của "heap" hoặc phân bổ thời gian chạy nói chung, trừ trường hợp bạn có thể sử dụng trình biên dịch có thể lưu trữ để biên dịch các phương thức mới một cách nhanh chóng. Các phương thức không được "phân bổ" như các đối tượng và chúng không "được phân bổ" liên quan đến việc tạo đối tượng. Chúng chỉ tồn tại như một phần của chương trình trước khi một đối tượng duy nhất được khởi tạo. Ngay cả lambdas / đại biểu không được phân bổ trên bay. Trình biên dịch tạo các lớp theo yêu cầu để thực hiện các đối tượng mã có vẻ động này và chúng cũng tồn tại như một phần của hình ảnh mã byte trên đĩa.

CẬP NHẬT mỗi bình luận:

Tiêu chuẩn JVM có điều này để nói:

2.5.4. Khu vực phương pháp

Máy ảo Java có một vùng phương thức được chia sẻ giữa tất cả các luồng của Máy ảo Java. Vùng phương thức tương tự với vùng lưu trữ cho mã được biên dịch của ngôn ngữ thông thường hoặc tương tự với phân đoạn "văn bản" trong một quy trình của hệ điều hành. Nó lưu trữ các cấu trúc trên mỗi lớp như nhóm dữ liệu phương thức, trường và phương thức hằng số thời gian chạy và mã cho các phương thức và hàm tạo, bao gồm các phương thức đặc biệt (§2.9) được sử dụng trong khởi tạo giao diện lớp và cá thể và khởi tạo giao diện.

Vùng phương thức được tạo khi khởi động máy ảo. Mặc dù khu vực phương thức là một phần logic của heap, các triển khai đơn giản có thể chọn không thu gom rác hoặc nén nó. Phiên bản đặc tả Máy ảo Java này không bắt buộc vị trí của vùng phương thức hoặc các chính sách được sử dụng để quản lý mã được biên dịch. Vùng phương thức có thể có kích thước cố định hoặc có thể được mở rộng theo yêu cầu của tính toán và có thể được ký hợp đồng nếu vùng phương thức lớn hơn trở nên không cần thiết. Bộ nhớ cho vùng phương thức không cần phải liền kề nhau.

Vì vậy, rõ ràng là (1) có thông số kỹ thuật không cho biết cách thực hiện, nhưng (2) nó tương tự như khu vực lưu trữ cho mã được biên dịch của một ngôn ngữ thông thường, nghĩa là. đoạn văn bản. Đây là điểm tôi đang thực hiện.


Những gì bạn đang nói có ý nghĩa, nhưng điều đó có thực sự được đảm bảo bởi JLS không? Thông thường, JLS cung cấp cho người thực hiện rất nhiều thời gian trong các câu hỏi như thế này.
Jörg W Mittag

Không chắc chắn về điểm đó, @ JörgWMittag. Bạn có thể đúng. Điểm tôi đã cố gắng thực hiện là "new T ()" không phân bổ một thể hiện mới của một phương thức. Đối với các chi tiết cụ thể của JVM, các trình nạp lớp thực sự lưu trữ mã byte trong heap và tôi đoán có thể có các kịch bản trong đó các lớp được khởi tạo và thậm chí cả rác được thu thập. Nhưng đó là chi tiết triển khai của thời gian chạy và về mặt khái niệm, heap tôi đang nói đến là heap "người dùng". Lớp & phương thức không được coi là dữ liệu trong ngữ cảnh người dùng thông thường. Nhưng vì chúng ta cũng có thể điều khiển trình nạp lớp từ vùng người dùng, tôi đoán là tôi không biết.
codenheim

JLS thậm chí không nói về một đống, phải không? Hoàn toàn hợp pháp khi triển khai Java với một ngăn xếp động và không có đống thay vì một ngăn xếp có kích thước cố định hữu hạn và một đống động. JLS cũng không nói gì về JVM, việc triển khai Java mà không cần JVM là hoàn toàn hợp lệ.
Jörg W Mittag

Bạn đang tham khảo JLS, nhưng tôi đang nói về JVM. Tiêu chuẩn JVM chắc chắn thảo luận về heap. Bạn phải cung cấp một phạm vi / vòng đời thay đổi thoát khỏi phạm vi cục bộ của ngăn xếp. Về những gì có thể về mặt lý thuyết, tôi thích nghĩ về các "triển khai đã biết". Tôi khá chắc chắn rằng việc thực hiện một JVM đầy đủ mà không có một đống nguyên thủy là một công việc khó khăn, hoặc thậm chí là không thể, vì JVM không phải là một máy ngăn xếp thuần túy. Sự hiểu biết của tôi về các máy Forth và các kiến ​​trúc ngăn xếp thuần túy khác, là có thể nếu một nguyên thủy tồn tại để truy cập biến ngẫu nhiên, nhưng tôi chưa thấy nó.
codenheim

@ JörgWMittag - Tôi đã thêm vào câu trả lời một cái gì đó có thể quan tâm cho cuộc thảo luận của chúng tôi. Vấn đề là tôi đã vẽ một sự tương tự với đoạn mã hoặc đoạn văn bản truyền thống trong các hệ thống thời gian chạy thông thường.
codenheim

-4

đối tượng được phân bổ trong bộ nhớ heap. Đối tượng được phân bổ vị trí cho tất cả biến đối tượng được tạo và hủy khi đối tượng bị hủy. Biến đối tượng cũng được phân bổ trong bộ nhớ heap. Và biến cục bộ được tạo trong ngăn xếp tại thời điểm khi phương pháp được gọi.


1
Điều này dường như chỉ lặp lại thông tin được cung cấp trong các câu trả lời trước đó.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.