Các phương thức tĩnh và biến tĩnh được lưu trữ ở đâu trong Java?


115

Ví dụ:

class A {
    static int i=0;
    static int j;

   static void method() {
       // static k=0; can't use static for local variables only final is permitted
       // static int L;
    }
}

Các biến này sẽ được lưu trữ ở đâu trong Java, trong heap hoặc trong bộ nhớ ngăn xếp? Chúng được lưu trữ như thế nào?


2
rất liên kết hữu ích để hiểu Thu gom rác trên trang web chính thức của Oracle: oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/...
Arnav Joshi

Câu trả lời:


144

Các phương thức tĩnh (trên thực tế là tất cả các phương thức) cũng như các biến tĩnh được lưu trữ trong PermGenphần của heap, vì chúng là một phần của dữ liệu phản chiếu (dữ liệu liên quan đến lớp, không liên quan đến cá thể).

Cập nhật để làm rõ :

Lưu ý rằng chỉ các biến và giá trị kỹ thuật của chúng (nguyên thủy hoặc tham chiếu) được lưu trữ trong không gian PermGen.

Nếu biến tĩnh của bạn là một tham chiếu đến một đối tượng thì bản thân đối tượng đó được lưu trữ trong các phần bình thường của heap (thế hệ trẻ / già hoặc không gian sống sót). Các đối tượng đó (trừ khi chúng là các đối tượng bên trong như các lớp, v.v.) không được lưu trữ trong không gian PermGen.

Thí dụ:

static int i = 1; //the value 1 is stored in the PermGen section
static Object o = new SomeObject(); //the reference(pointer/memory address) is stored in the PermGen section, the object itself is not.


Một từ về thu gom rác:

Đừng không dựa vào finalize()là nó không được bảo đảm để chạy. JVM hoàn toàn phụ thuộc vào quyết định khi nào chạy bộ thu gom rác và những gì cần thu gom, ngay cả khi một đối tượng đủ điều kiện để thu gom rác.

Tất nhiên bạn có thể đặt một biến tĩnh thành null và do đó xóa tham chiếu đến đối tượng trên heap nhưng điều đó không có nghĩa là trình thu gom rác sẽ thu thập nó (ngay cả khi không còn tham chiếu nào nữa).

Ngoài ra, finalize()chỉ chạy một lần, vì vậy bạn phải đảm bảo rằng nó không ném ra các ngoại lệ hoặc ngăn cản việc thu thập đối tượng. Nếu bạn tạm dừng hoàn thiện thông qua một số ngoại lệ, finalize()sẽ không được gọi trên cùng một đối tượng lần thứ hai.

Lưu ý cuối cùng : cách lưu trữ mã, dữ liệu thời gian chạy, v.v. phụ thuộc vào JVM được sử dụng, tức là HotSpot có thể làm điều đó khác với JRockit và điều này thậm chí có thể khác nhau giữa các phiên bản của cùng một JVM. Phần trên dựa trên HotSpot cho Java 5 và 6 (về cơ bản chúng giống nhau) vì tại thời điểm trả lời, tôi muốn nói rằng hầu hết mọi người đã sử dụng các JVM đó. Do những thay đổi lớn trong mô hình bộ nhớ của Java 8, các câu lệnh trên có thể không đúng với Java 8 HotSpot - và tôi đã không kiểm tra các thay đổi của Java 7 HotSpot, vì vậy tôi đoán những điều trên vẫn đúng với phiên bản đó, nhưng tôi không chắc ở đây.


1
Ahh bạn có chắc chắn về các biến tĩnh không? AFAIK PermGen chỉ lưu trữ các định nghĩa không phải giá trị thực.
Amir Raminfar

2
@Amir Tôi khá chắc chắn rằng bản thân biến được lưu trữ trong không gian permgen, mọi đối tượng được tham chiếu rất có thể sẽ được cấp phát trên heap. Điều này có thể thêm một số thông tin: stackoverflow.com/questions/3800444/…
Thomas

1
À vâng, định nghĩa biến được lưu trữ trong permgen. Nhưng giá trị sẽ nằm trong đống. Câu trả lời của bạn gợi ý rằng giá trị cũng được lưu trữ trong PermGen.
Amir Raminfar

1
@Matthew làm sao bạn hiểu câu trả lời của tôi? A nói rằng các biến được lưu trữ trong phần permgen (nguyên thủy / tham chiếu) không phải đối tượng mà chúng tham chiếu đến. Nó phụ thuộc vào cách bạn xem giá trị biến .
Thomas

1
@Nav không phải tất cả các phần của heap đều được thu thập rác theo mặc định và đôi khi các lớp và do đó các biến tĩnh không thể được thu thập vì trình tải lớp vẫn có tham chiếu trên chúng. Ngoài ra, bạn không nên dựa vào trình thu gom rác để chạy vì điều đó hoàn toàn phụ thuộc vào JVM (nó quyết định thời điểm chạy và những gì cần thu thập, bạn chỉ có thể cung cấp các gợi ý như "Tôi muốn bạn chạy gc ngay bây giờ" :)) .
Thomas

25

Các biến lớp (Biến tĩnh) được lưu trữ như một phần của Class objectliên kết với lớp đó. Đối tượng Class này chỉ có thể được tạo bởi JVM và được lưu trữ trong permanent generation.

Ngoài ra, một số người đã trả lời rằng nó được lưu trữ trong vùng non heap được gọi là Method Area.Even câu trả lời này không sai. Nó chỉ là một chủ đề gây tranh cãi liệu Khu vực Permgen có phải là một phần của đống hay không. Rõ ràng nhận thức của mỗi người là khác nhau. Theo ý kiến ​​của tôi, chúng tôi cung cấp không gian heap và không gian permgen khác nhau trong các đối số JVM. Vì vậy, đó là một giả định tốt để đối xử với họ khác nhau.

Một cách khác để xem nó

Các vùng bộ nhớ được tạo bởi trình quản lý bộ nhớ JVM trong thời gian chạy. Vùng nhớ có thể thuộc về vùng nhớ heap hoặc không thuộc vùng nhớ heap. Vùng hằng số thời gian chạy là biểu diễn thời gian chạy trên mỗi lớp hoặc trên mỗi giao diện của bảng hằng số trong tệp lớp. Mỗi vùng hằng số thời gian chạy được cấp phát từ vùng phương thức của máy ảo Java và các Biến tĩnh được lưu trữ trong Vùng phương thức này. Ngoài ra, không phải heap này không là gì ngoài vùng gen hoán vị. Vùng phương pháp thực tế là một phần của gen hoán vị. ( Tham khảo )

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


vùng phương thức không phải là một tập con của phần PermGen của bộ nhớ? Tại sao bạn lại hiển thị vùng phương thức là một phần của bộ nhớ không phải heap khi tôi nghĩ rằng chúng (PermGen cùng với vùng phương thức (lớp)) là một phần của vùng heap lớn hơn của JVM?
Kaveesh Kanwal

Đọc dòng cuối cùng -Also this non-heap is nothing but perm gen area.Actually Method area is part of perm gen.
Aniket Thakur

1
@AniketThakur bạn đã hiển thị vùng phương thức như một phần của bộ nhớ không phải heap nhưng theo tài liệu oracle, tại đây, docs.oracle.com/javase/specs/jvms/se7/html/… , có đề cập rằng vùng phương thức về mặt logic là một phần của đống.
Karan

21

Trước Java 8:

Các biến tĩnh được lưu trữ trong không gian permgen (còn được gọi là vùng phương thức).

PermGen Space còn được gọi là Method Area

PermGen Space được sử dụng để lưu trữ 3 thứ

  1. Dữ liệu cấp độ lớp (siêu dữ liệu)
  2. chuỗi thực tập
  3. biến tĩnh

Từ Java 8 trở đi

Các biến tĩnh được lưu trữ trong chính Heap.Từ Java 8 trở đi, Không gian PermGen đã bị loại bỏ và không gian mới có tên là MetaSpace được giới thiệu mà không phải là một phần của Heap nữa, không giống như Không gian Permgen trước đó. Meta-Space hiện diện trên bộ nhớ gốc (bộ nhớ do HĐH cung cấp cho một Ứng dụng cụ thể để sử dụng riêng) và giờ đây nó chỉ lưu trữ siêu dữ liệu lớp.

Các chuỗi xen kẽ và các biến tĩnh được chuyển vào chính heap.

Để biết thông tin chính thức, hãy tham khảo: JEP 122: Xóa bỏ không gian gen vĩnh viễn


khi bạn nói "heap yourself" cho các biến tĩnh> Java8, thì chính xác là: OldGen?
Ewoks

15

Đây là một câu hỏi với một câu trả lời đơn giản và một câu trả lời dài dòng.

Câu trả lời đơn giản là đống. Các lớp và tất cả dữ liệu áp dụng cho các lớp (không phải dữ liệu cá thể) được lưu trữ trong phần Tạo vĩnh viễn của heap.

Câu trả lời dài đã có trên tràn ngăn xếp:

Có một mô tả kỹ lưỡng về bộ nhớ và thu thập rác trong JVM cũng như một câu trả lời nói ngắn gọn hơn về nó.


3
Điều chắc chắn! Đừng quên ủng hộ những người đó nếu bạn thấy họ hữu ích.
Vasiliy Sharapov

11

Nó được lưu trữ trong heap được tham chiếu bởi định nghĩa lớp. Nếu bạn nghĩ về nó, nó không liên quan gì đến ngăn xếp vì không có phạm vi.


5

Ngoài câu trả lời của Thomas, biến tĩnh được lưu trữ trong vùng không phải đống được gọi là Vùng phương pháp.


4

Vì các biến tĩnh là các biến mức lớp, chúng sẽ lưu trữ " thế hệ vĩnh viễn " của bộ nhớ heap. Vui lòng xem xét điều này để biết thêm chi tiết về JVM. Hy vọng điều này sẽ hữu ích


3

biến tĩnh được lưu trữ trong heap


7
Biến static được lưu trong không gian PremGen trong bộ nhớ, giá trị của chúng được lưu trong Heap.
Akash5288
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.