Quản lý bộ nhớ trong Java

⚡ Tóm tắt thông minh

Quản lý bộ nhớ trong Java Giải thích cách JVM phân chia bộ nhớ thời gian chạy giữa Stack, Heap, Codevà các vùng tĩnh, cách các tham chiếu đối tượng truyền trong quá trình gọi phương thức, và cách Trình thu gom rác (Garbage Collector) thu hồi các đối tượng không thể truy cập được để đảm bảo ứng dụng hoạt động ổn định và không bị rò rỉ bộ nhớ.

  • 🧠 Sơ đồ bố trí bộ nhớ JVM: Java Bộ nhớ được chia thành Heap cho các đối tượng, Stack cho các khung phương thức và các biến cục bộ, cộng thêm các vùng riêng biệt cho mã byte và dữ liệu tĩnh.
  • 📚 So sánh Stack và Heap: Các khung ngăn xếp tuân theo nguyên tắc Vào sau Ra trước (LIFO) và lưu trữ các kiểu dữ liệu nguyên thủy và tham chiếu, trong khi vùng nhớ Heap chứa mọi đối tượng được tạo bằng toán tử new.
  • ♻️ Thu gom rác thải: Người thu gom rác tracks đảm bảo khả năng truy cập thông qua chuỗi tham chiếu và tự động thu hồi bộ nhớ từ các đối tượng mà không luồng nào có thể truy cập được.
  • Những nhà sưu tập hiện đại: Các khối lượng công việc sản xuất ngày càng phụ thuộc vào G1, ZGC và Shenandoah để thu thập dữ liệu với thời gian tạm dừng thấp trên các vùng nhớ dung lượng nhiều gigabyte.
  • 🧪 Ví dụ thực hành: Hướng dẫn từng bước dành cho sinh viên sẽ chỉ ra khi nào các tham chiếu đủ điều kiện để được thu thập và cách việc đặt null cho các tham chiếu giải phóng đối tượng cơ bản.

Quản lý bộ nhớ trong Java

Bộ nhớ ngăn xếp là gì? Java?

Bộ nhớ ngăn xếp trong Java Stack là vùng bộ nhớ JVM lưu trữ các khung phương thức, biến cục bộ và biến tham chiếu cho mỗi luồng. Stack luôn được truy cập theo thứ tự Vào sau Ra trước (LIFO), vì vậy phương thức được gọi gần đây nhất nằm ở trên cùng, và các biến cục bộ của nó được đẩy vào và lấy ra cùng với khung phương thức.

Mỗi sợi chỉ trong Java Máy ảo nhận được ngăn xếp riêng, giúp giữ cho các lời gọi phương thức được cô lập và an toàn cho đa luồng theo thiết kế. Các biến cục bộ nguyên thủy như int, boolean và double nằm trực tiếp bên trong khung, trong khi các tham chiếu đối tượng được lưu trữ trên ngăn xếp trỏ đến các đối tượng được cấp phát trên vùng nhớ Heap.

Bộ nhớ Heap là gì? Java?

Bộ nhớ heap là vùng bộ nhớ dùng chung của JVM chứa mọi thứ. Java Đối tượng và mảng được tạo bằng toán tử `new`, cùng với bất kỳ biến tham chiếu nào thuộc về các đối tượng đó dưới dạng các trường thể hiện. Không giống như Stack, Heap được chia sẻ giữa tất cả các luồng, đó là lý do tại sao việc truy cập đối tượng thường yêu cầu đồng bộ hóa.

Vùng Heap là khu vực mà bộ thu gom rác quản lý. Các JVM HotSpot hiện đại chia vùng Heap thành Thế hệ trẻ (Young Generation) dành cho các đối tượng có vòng đời ngắn và Thế hệ cũ (Old Generation) dành cho các đối tượng có vòng đời dài, với siêu dữ liệu của lớp được lưu trữ trong một vùng riêng biệt gọi là Metaspace.

Phân bổ bộ nhớ trong Java

Phân bổ bộ nhớ trong Java Đây là quá trình mà JVM dành riêng các vùng bộ nhớ ảo cho các biến và các thể hiện của lớp và cấu trúc trong quá trình thực thi chương trình. Bộ nhớ không được cấp phát cho đối tượng khi khai báo; chỉ có một tham chiếu được tạo ra. Việc cấp phát đối tượng thực sự diễn ra thông qua toán tử `new`, vì vậy mọi đối tượng đều nằm trên Heap.

Java Việc phân bổ bộ nhớ được chia thành các phần sau:

  1. ban ơn
  2. Sắp xếp
  3. Code
  4. tĩnh

Việc phân chia bộ nhớ này là cần thiết để quản lý hiệu quả thời gian chạy.

  • Code phần này chứa nội dung đã được biên dịch của bạn mã byte.
  • Sắp xếp cửa hàng bách hóa phương pháp, biến cục bộ và biến tham chiếu.
  • ban ơn phần chứa đối tượng và cũng có thể chứa các biến tham chiếu được lưu trữ dưới dạng các trường của đối tượng.
  • tĩnh phần này chứa dữ liệu tĩnh và phương thức tĩnh Được chia sẻ trên tất cả các trường hợp.

Sự khác biệt giữa biến cục bộ và biến thể

Hiểu được vị trí của từng loại biến trong JVM giúp giải thích hành vi của Stack và Heap. biến cá thể được tuyên bố bên trong một lớp nhưng bên ngoài bất kỳ phương thức nào.và nó tồn tại trên Heap như một phần của đối tượng.

class Student{ 
int num; // num is instance variable 
public void showData{}

A biến cục bộ được tuyên bố bên trong một phương thức, bao gồm cả các đối số của phương thức.và nằm trên ngăn xếp bên trong khung hoạt động.

public void sum(int a){

int x = a + 3;

// a, x are local variables

}

Sự khác biệt giữa ngăn xếp và đống

Ngăn xếp (Stack) và vùng nhớ Heap giải quyết các vấn đề khác nhau bên trong JVM. Ngăn xếp cung cấp cho mỗi luồng khả năng cấp phát bộ nhớ nhanh chóng và có tính xác định cho dữ liệu tồn tại ngắn hạn gắn liền với phạm vi phương thức, trong khi vùng nhớ Heap cung cấp một vùng chia sẻ cho các đối tượng tồn tại lâu dài mà bất kỳ luồng nào cũng có thể tham chiếu. Video ngắn dưới đây tóm tắt sự khác biệt trước khi đến phần hướng dẫn chi tiết tiếp theo.

Nhấp chuột đây nếu video không thể truy cập được

Để thấy cách Stack và Heap phối hợp với nhau, hãy xem xét một phương thức main gọi phương thức m1.

public void m1{
int x = 20;
}

Trong ngăn xếp JVM, một khung được tạo cho phương thức m1.

Java Ngăn xếp và đống

Biến x trong m1 cũng được tạo trong khung cho m1 trên Stack, như hình ảnh bên dưới.

Java Ngăn xếp và đống

Phương thức m1 gọi phương thức m2. Trong ngăn xếp, một khung mới được tạo cho m2 nằm trên khung của m1.

Java Ngăn xếp và đống

Java Ngăn xếp và đống

Các biến cục bộ b và c cũng được tạo bên trong khung cho m2 trên Stack.

public void m2(int b){
boolean c;
}

Tiếp theo, m2 gọi phương thức m3. Một lần nữa, một khung cho m3 được tạo ở đầu Stack, như hình bên dưới.

Java Ngăn xếp và đống

Java Ngăn xếp và đống

Giả sử phương thức m3 tạo một đối tượng cho lớp Account, đối tượng này có hai thuộc tính. Biến thể hiện int p và int q.

class Account {
    int p;
    int q;
}

Đây là mã nguồn của phương pháp m3.

public void m3(){
    Account ref = new Account();
    // more code
}

Câu lệnh `new Account()` tạo một đối tượng `Account` trên vùng nhớ Heap.

Java Ngăn xếp và đống

Biến tham chiếu ref được tạo trên Stack bên trong khung cho m3.

Java Ngăn xếp và đống

Toán tử gán làm cho biến tham chiếu trỏ đến đối tượng trên vùng nhớ Heap.

Java Ngăn xếp và đống

Sau khi phương thức hoàn tất quá trình thực thi, quyền điều khiển sẽ được trả về phương thức gọi, trong trường hợp này là phương thức m2.

Java Ngăn xếp và đống

Khung dữ liệu cho phương thức m3 đã được xóa khỏi ngăn xếp.

Java Ngăn xếp và đống

Vì biến tham chiếu không còn trỏ đến đối tượng trên vùng nhớ Heap nữa, nên đối tượng đó đủ điều kiện để được thu gom rác.

Java Ngăn xếp và đống

Sau khi phương thức m2 kết thúc, nó sẽ bị loại bỏ khỏi ngăn xếp và tất cả các biến của nó sẽ không còn khả dụng. Điều tương tự cũng xảy ra với phương thức m1, và cuối cùng quyền điều khiển sẽ trở lại phương thức chính.

Điều gì sẽ xảy ra nếu một đối tượng giữ một tham chiếu khác dưới dạng biến thể hiện của nó?

public static void main(String args[]) {
    A parent = new A();
    // more code
}
class A {
    B child = new B();
    int e;
}
class B {
    int c;
    int d;
}

Trong trường hợp này, biến tham chiếu child nằm trên Heap như một phần của đối tượng A, và lần lượt trỏ đến đối tượng B của chính nó, như minh họa bên dưới.

Java Ngăn xếp và đống

Thu gom rác là gì Java?

Thu gom rác ở Java Đây là quá trình mà JVM thực hiện quản lý bộ nhớ tự động. Trình thu gom rác (Garbage Collector) tìm các đối tượng không còn được truy cập bởi bất kỳ tham chiếu nào và thu hồi bộ nhớ của chúng. Việc cấp phát bộ nhớ động diễn ra thông qua toán tử `new`, và bộ nhớ được cấp phát cho đến khi chương trình không còn giữ bất kỳ tham chiếu nào đến đối tượng đó nữa.

Khi không còn tham chiếu nào đến đối tượng, đối tượng đó được coi là không còn cần thiết nữa và bộ nhớ mà nó chiếm dụng có thể được giải phóng. Không cần thiết phải hủy bỏ đối tượng một cách rõ ràng vì Java Việc giải phóng bộ nhớ được thực hiện tự động thông qua Trình thu gom rác.

Kỹ thuật đằng sau điều này được gọi là Thu gom rác thảiCác chương trình không giải phóng được bộ nhớ cuối cùng sẽ bị lỗi khi không còn gì để phân bổ nữa. Những chương trình như vậy được gọi là có lỗi. rò rỉ bộ nhớ. Thu gom rác ở Java chạy tự động Trong suốt vòng đời của chương trình, điều này giúp loại bỏ gánh nặng phân bổ lại thủ công và giảm nguy cơ rò rỉ.

Ngược lại, trong ngôn ngữ C, lập trình viên chịu trách nhiệm giải phóng bộ nhớ được cấp phát động thông qua hàm free(). Đây là lý do tại sao... Java Quản lý bộ nhớ mang lại một lợi thế mạnh mẽ.

Các JVM HotSpot hiện đại tích hợp sẵn một số bộ thu gom rác được tinh chỉnh cho các khối lượng công việc khác nhau. Bộ thu gom rác G1 mặc định hướng đến sự cân bằng giữa thông lượng và thời gian tạm dừng trên các vùng nhớ heap nhiều gigabyte. ZGC và Shenandoah hướng đến thời gian tạm dừng dưới mili giây trên các vùng nhớ heap rất lớn, điều này khiến chúng trở nên...tracĐặc biệt quan trọng đối với các dịch vụ nhạy cảm với độ trễ. Việc lựa chọn bộ thu thập phù hợp và điều chỉnh kích thước Young Generation, Old Generation và Metaspace là một kỹ năng cốt lõi. Java Công việc biểu diễn.

Lưu ý: Tất cả các đối tượng đều được tạo trong vùng nhớ Heap, là vùng mà trình thu gom rác quản lý.

Ví dụ: Tìm hiểu cơ chế thu gom rác trong Java

Hướng dẫn này trình bày khi nào các tham chiếu đủ điều kiện để được thu gom vào bộ nhớ cache (Garbage Collection) bên trong một chương trình đơn giản.

Bước 1) Sao chép đoạn mã sau vào trình soạn thảo.

class Student{
int a;
int b;
  public void setData(int c,int d){
    a=c;
    b=d;
  }
  public void showData(){
    System.out.println("Value of a = "+a);
    System.out.println("Value of b = "+b);
  }
  public static void main(String args[]){
    Student s1 = new Student();
    Student s2 = new Student();
    s1.setData(1,2);
    s2.setData(3,4);
    s1.showData();
    s2.showData();
    //Student s3;
    //s3=s2;
    //s3.showData();
    //s2=null;
    //s3.showData();
    //s3=null;
    //s3.showData();
  }
}

Bước 2) Lưu, biên dịch và chạy mã. Như hình minh họa, hai đối tượng và hai biến tham chiếu được tạo ra.

 Cơ chế thu gom rác

Bước 3) Bỏ dấu chú thích ở dòng 20, 21 và 22. Lưu, biên dịch và chạy mã.

Bước 4) Như thể hiện trong sơ đồ bên dưới, hai biến tham chiếu hiện đang trỏ đến cùng một đối tượng.

Cơ chế thu gom rác

Bước 5) Bỏ dấu chú thích ở dòng 23 và 24. Lưu, biên dịch và chạy mã.

Bước 6) Như hình minh họa bên dưới, s2 trở thành null, nhưng s3 vẫn trỏ đến đối tượng, do đó đối tượng chưa đủ điều kiện để được thu gom rác.

 Cơ chế thu gom rác

Bước 7) Bỏ dấu chú thích ở dòng 25 và 26. Lưu, biên dịch và chạy mã.

Bước 8) Tại thời điểm này, không còn tham chiếu nào trỏ đến đối tượng nữa, vì vậy nó đủ điều kiện để được thu gom rác. Trình thu gom rác sẽ loại bỏ nó khỏi bộ nhớ và không có cách nào để khôi phục lại nó.

 Tìm hiểu người thu gom rác

Cách xóa một đối tượng trong Java?

Java Không cung cấp toán tử xóa thủ công, vì vậy phương pháp tiêu chuẩn là loại bỏ mọi tham chiếu đến đối tượng để Trình thu gom rác có thể thu hồi nó.

1) Để một đối tượng đủ điều kiện được đưa vào quá trình thu gom rác tự động, hãy gán giá trị null cho mọi biến tham chiếu trỏ đến đối tượng đó.

2) Các kiểu dữ liệu nguyên thủy không phải là đối tượng, vì vậy chúng không thể được gán giá trị null. Bộ nhớ của chúng được giải phóng tự động khi khung ngăn xếp xung quanh bị loại bỏ.

Cách xóa một đối tượng trong Java

Câu Hỏi Thường Gặp

Stack lưu trữ các khung phương thức, biến cục bộ và tham chiếu theo thứ tự Vào sau Ra trước (LIFO) cho mỗi luồng. Heap lưu trữ tất cả các đối tượng được tạo bằng từ khóa `new` và được chia sẻ giữa các luồng, đó là lý do tại sao bộ thu gom rác (Garbage Collector) quản lý nó.

Bộ thu gom rác (Garbage Collector) duyệt qua các chuỗi tham chiếu từ các gốc GC như các luồng đang hoạt động và các trường tĩnh. Bất kỳ đối tượng nào không thể truy cập được từ gốc đều được coi là không thể truy cập và đủ điều kiện để được thu hồi trong chu kỳ thu gom tiếp theo.

Thế hệ trẻ lưu giữ các đối tượng có vòng đời ngắn trong không gian Eden và Survivor. Thế hệ cũ lưu giữ các đối tượng tồn tại qua nhiều bộ sưu tập. Metaspace là một vùng bộ nhớ gốc lưu trữ siêu dữ liệu lớp và đã thay thế PermGen cũ hơn. Java 8.

G1 là chế độ mặc định và phù hợp với hầu hết các khối lượng công việc trên các heap nhiều gigabyte. ZGC và Shenandoah nhắm đến các khoảng dừng dưới mili giây trên các heap rất lớn và là lựa chọn tốt cho các dịch vụ nhạy cảm về độ trễ chạy trên... Java 17 trở lên.

Đặt mọi tham chiếu trỏ đến đối tượng thành null, hoặc để các tham chiếu đó nằm ngoài phạm vi khi khung ngăn xếp của chúng được lấy ra. Khi không còn tham chiếu nào còn hoạt động đến đối tượng, Trình thu gom rác sẽ thu hồi bộ nhớ Heap của nó.

Đúng vậy. Các công cụ tinh chỉnh dựa trên AI phân tích nhật ký GC, tốc độ phân bổ và biểu đồ tạm dừng để đề xuất kích thước Heap, cờ thu gom và tỷ lệ Young Generation. Chúng rút ngắn chu kỳ phản hồi so với việc tinh chỉnh thủ công, đặc biệt là đối với các khối lượng công việc G1, ZGC và Shenandoah.

Các nền tảng quan sát dựa trên AI thu thập các bản ghi lỗi bộ nhớ heap và số liệu thời gian thực, sau đó nhóm các đồ thị đối tượng được lưu giữ để gắn cờ các lớp và chuỗi tham chiếu đáng ngờ. Điều này giúp phát hiện các ứng cử viên rò rỉ nhanh hơn so với phân tích bộ nhớ heap thủ công và giúp các nhóm xác định chính xác nguyên nhân gốc rễ trong môi trường sản xuất.

Tóm tắt bài viết này với: