Garbage Collection trong Java là một quá trình tự động quản lý bộ nhớ của JVM (Java Virtual Machine). Nó tự động quản lý và thu hồi bộ nhớ của các đối tượng không còn sử dụng, giúp giảm thiểu rủi ro tổn thất bộ nhớ và giảm thiểu tình trạng lỗi “OutOfMemoryError”.
Các bài viết liên quan:
Trong Java, bộ nhớ được chia thành hai loại chính là Stack và Heap. Stack lưu trữ các biến cục bộ và các giá trị địa phương, trong khi Heap lưu trữ các đối tượng và các mảng. Garbage Collection chủ yếu hoạt động trên Heap để tìm và thu hồi các đối tượng không còn sử dụng.
Các đối tượng được coi là không còn sử dụng khi không còn một chuỗi tham chiếu nào tới chúng. Garbage collector sẽ duyệt qua tất cả các đối tượng trên Heap và tìm các đối tượng không còn được tham chiếu, sau đó thu hồi bộ nhớ của chúng.
Việc Garbage Collection tự động sẽ giúp giảm thiểu rủi ro gây ra lỗi về bộ nhớ và giúp cho chương trình Java của bạn chạy mượt mà hơn. Tuy nhiên, việc sử dụng Garbage Collection cũng có thể làm chậm tốc độ chương trình của bạn, do đó, chúng ta cần lưu ý trong việc sử dụng và quản lý bộ nhớ trong chương trình Java của mình.
Cơ chế hoạt động garbage collection
Garbage collection là quá trình tự động thu dọn bộ nhớ không sử dụng trong chương trình. Cơ chế hoạt động của garbage collection thường bao gồm hai bước chính:
- Xác định các đối tượng không sử dụng: Garbage collector quét qua bộ nhớ và xác định các đối tượng không được tham chiếu đến bởi bất kỳ phần tử nào của chương trình.
- Thu hồi bộ nhớ: Sau khi xác định các đối tượng không sử dụng, garbage collector sẽ thu hồi bộ nhớ của chúng. Quá trình này bao gồm việc giải phóng bộ nhớ đã được cấp phát cho đối tượng và chuyển các khối bộ nhớ được sử dụng trở lại cho bộ nhớ tổng thể của hệ thống.
Tùy thuộc vào loại garbage collector, các bước này có thể được thực hiện theo nhiều cách khác nhau để đảm bảo hiệu quả và hiệu suất cao nhất.
Các loại garbage collection
Có nhiều loại garbage collection khác nhau, tùy thuộc vào cách thức thu thập và phân tích đối tượng để quyết định xem chúng có thể được giải phóng hay không. Dưới đây là một số loại garbage collection phổ biến:
- Mark-and-sweep: Đây là phương pháp thu thập rác truyền thống nhất. Nó hoạt động bằng cách đánh dấu các đối tượng không sử dụng trong bộ nhớ, sau đó quét lại để giải phóng chúng. Phương pháp này có thể làm tốn thời gian quét toàn bộ bộ nhớ, tuy nhiên nó hiệu quả với các ứng dụng lớn.
- Copying: Phương pháp này chia bộ nhớ thành hai vùng bằng nhau, chỉ sử dụng một trong số chúng vào bất kỳ thời điểm nào. Garbage collector sao chép các đối tượng còn lại từ vùng này sang vùng còn lại, sau đó giải phóng vùng cũ.
- Generational: Phương pháp này sắp xếp các đối tượng theo độ tuổi của chúng. Các đối tượng mới được cấp phát ở vùng nhớ mới nhất, còn các đối tượng cũ hơn được cấp phát ở các vùng nhớ khác. Garbage collector chủ yếu tập trung vào các đối tượng trẻ và thực hiện các thu thập rác thường xuyên trên chúng.
- Incremental: Phương pháp này phân chia quá trình thu thập rác thành nhiều bước nhỏ hơn để tránh làm gián đoạn chương trình khi quá trình thu thập rác diễn ra. Garbage collector sẽ thực hiện một số bước mỗi lần, để cho phép ứng dụng tiếp tục hoạt động trong khi garbage collector đang chạy.
Mỗi loại garbage collection có những ưu điểm và hạn chế khác nhau, và lựa chọn loại garbage collection thích hợp cần phù hợp với ứng dụng cụ thể.
Ví dụ về sử dụng garbage collection trong java
Ví dụ 1:
String str1 = new String("Hello"); String str2 = str1; str1 = null;
Trong ví dụ trên, chúng ta tạo ra một đối tượng String với giá trị “Hello” và gán nó cho biến str1. Sau đó chúng ta tạo ra một biến str2 và gán nó bằng str1. Tại thời điểm này, cả str1 và str2 đều trỏ đến cùng một đối tượng. Tiếp theo, chúng ta gán giá trị null cho str1. Tại thời điểm này, đối tượng “Hello” không còn được tham chiếu tới bởi bất kỳ biến nào nữa, và sẽ được Garbage Collector thu hồi.
Ví dụ 2:
List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list = null;
Trong ví dụ trên, chúng ta tạo ra một đối tượng ArrayList và thêm vài phần tử vào nó. Sau đó, chúng ta gán giá trị null cho biến list. Tại thời điểm này, đối tượng ArrayList không còn được tham chiếu tới bởi bất kỳ biến nào nữa, và sẽ được Garbage Collector thu hồi.
Lưu ý rằng Garbage Collection hoạt động tự động và không thể điều khiển, nó chỉ hoạt động khi bộ nhớ hết.