*Trong một buổi phỏng vấn gần đây, mình đã được hỏi về những tính năng nổi bật của Java. Trong đó, mình đã đề cập đến Garbage Collection (GC) - bộ thu gom rác tự động. Điều này giúp lập trình viên không phải quản lý bộ nhớ như trong C/C++. Tuy nhiên, khi được hỏi làm sao GC biết vùng nhớ nào không còn được sử dụng, mình đã không thể trả lời. Điều này khiến mình nhận ra mình cần tìm hiểu sâu hơn về cách hoạt động thực sự của Garbage Collection. Trong bài viết này, chúng ta sẽ cùng nhau khám phá câu hỏi này một cách chi tiết nhất.
1. Garbage Collection Là Gì?
Garbage Collection, hay thu gom rác, là một cơ chế trong Java giúp tự động giải phóng bộ nhớ cho các đối tượng không còn được sử dụng. Nhờ vào GC, lập trình viên không cần phải quản lý bộ nhớ thủ công, từ đó giảm thiểu tình trạng rò rỉ bộ nhớ (memory leaks). Qua đó, không gian bộ nhớ có thể được sử dụng hiệu quả hơn.
1.1 Đối Tượng Chết (Dead Objects)
Trong bộ nhớ heap, các đối tượng trở thành "chết" khi không còn có bất kỳ tham chiếu nào trỏ đến chúng. Các đối tượng này sẽ được GC thu gom khi cần, làm sạch bộ nhớ cho các đối tượng khác sử dụng.
2. Cách Định Nghĩa Garbage
2.1 Thuật Toán Đếm Tham Chiếu (Reference Counting)
Thuật toán này giữ một trường trong phần tiêu đề của đối tượng để lưu số lượng tham chiếu. Khi số lượng tham chiếu giảm xuống 0, đối tượng đó sẽ được thu gom. Tuy nhiên, thuật toán này không xử lý được việc tham chiếu vòng tròn, dẫn đến tình trạng bộ nhớ không được giải phóng.
2.2 Thuật Toán Phân Tích Khả Dụng (Reachability Analysis)
Chúng ta có thể giải quyết vấn đề trên bằng thuật toán Reachability Analysis. GC xác định các đối tượng có thể truy cập từ các "GC roots". Nếu không thể truy cập, tức là đối tượng không khả dụng, và sẽ bị thu gom.
GC Roots Là Gì?
GC roots bao gồm biến cục bộ, các đối tượng static, và các đối tượng được tham chiếu qua JNI. Đây là các điểm bắt đầu để GC kiểm tra trạng thái của các đối tượng trong bộ nhớ.
3. Cách Garbage Collection Hoạt Động
GC sử dụng nhiều thuật toán khác nhau để thu gom rác tùy thuộc vào cách mà bộ nhớ được chia. Một vài thuật toán phổ biến bao gồm:
3.1 Thuật Toán Sao Chép (Copying Algorithm)
Thuật toán sao chép chia bộ nhớ thành hai phần bằng nhau và chỉ sử dụng một phần vào thời điểm. Khi vùng nhớ đầy, đối tượng còn sống sẽ được sao chép sang phần còn lại.
3.2 Thuật Toán Đánh Dấu và Quét (Mark-Sweep Algorithm)
Thuật toán phổ biến này thực hiện hai bước: đánh dấu các đối tượng và quét các đối tượng đã đánh dấu.
3.3 Thuật Toán Đánh Dấu và Gom (Mark-Compact Algorithm)
Sau khi đánh dấu, các đối tượng còn sống sẽ được gom lại về một phía, loại bỏ phân mảnh bộ nhớ.
3.4 Thu Gom Theo Thế Hệ (Generational Collection Algorithm)
Phương pháp này chia bộ nhớ thành các vùng theo tuổi thọ của đối tượng, giúp tối ưu hiệu suất việc thu gom rác.
Minor GC vs Major GC
- Minor GC: Xảy ra khi Young Generation đầy, nhanh chóng.
- Major GC: Xảy ra khi Old Generation đầy hoặc theo yêu cầu, chậm hơn.
4. Kết Luận
Bài viết đã giúp bạn hiểu rõ hơn về Garbage Collection trong Java, từ cách nó tự động thu gom rác đến các thuật toán được sử dụng. Hi vọng những thông tin này sẽ hữu ích cho bạn trong quá trình học tập và phát triển.
Nếu bạn có thắc mắc hoặc góp ý, hãy để lại câu hỏi dưới bài viết này nhé!