Garbage Collection hoạt động như thế nào?

Quá trình garbage collection thường diễn ra theo các bước cốt lõi: đánh dấu, quét và dọn dẹp. Đầu tiên, bộ thu gom xác định các đối tượng nào vẫn còn được tham chiếu từ gốc (root set) như biến toàn cục, biến cục bộ trong stack hay luồng đang chạy. Những đối tượng không có đường dẫn đến root được đánh dấu là rác. Sau đó, GC thu hồi bộ nhớ của các đối tượng rác này, thường bằng cách nén bộ nhớ để giảm phân mảnh. Tuỳ vào thuật toán, GC có thể tạm dừng chương trình (stop-the-world) hoặc chạy song song với ứng dụng.
Các thành phần tham gia vào quá trình GC
- Root set: Điểm bắt đầu truy vết, gồm thanh ghi CPU, stack frame, biến tĩnh.
- Heap: Vùng nhớ động nơi cấp phát đối tượng.
- Bộ thu gom: Module thực thi thuật toán dọn dẹp.
- Finalizer: Phương thức đặc biệt cho phép đối tượng dọn dẹp tài nguyên trước khi bị thu hồi.
- Giữ tham chiếu không cần thiết: Để biến tĩnh hoặc collection giữ đối tượng lâu hơn cần thiết, khiến GC không thể thu hồi. Cách tránh: set reference = null khi không dùng, hoặc dùng WeakReference nếu thích hợp.
- Tạo quá nhiều đối tượng tạm thời: Ví dụ nối chuỗi trong vòng lặp bằng toán tử + (thay vào đó dùng StringBuilder). Điều này làm tăng tần suất GC và giảm hiệu năng.
- Gọi System.gc() hoặc GC.Collect() một cách bừa bãi: Đây là gợi ý, không phải lệnh buộc. Gọi quá nhiều có thể gây lãng phí CPU và ngược lại làm ứng dụng chậm đi. Chỉ nên dùng trong tình huống kiểm thử hoặc biết chắc lúc đó là thích hợp.
- Hiểu sai về finalizer: Finalizer không được đảm bảo thời gian chạy và có thể gây ra hiện tượng “resurrection” – đối tượng được hồi sinh trong finalize, gây lỗi logic. Nên tránh dùng finalizer, thay bằng IDisposable (C#) hoặc try-with-resources (Java).
Các loại thuật toán Garbage Collection phổ biến
Mỗi ngôn ngữ và runtime áp dụng những thuật toán GC khác nhau, phù hợp với đặc thù hiệu năng và bộ nhớ.
Reference Counting (Đếm tham chiếu)
Mỗi đối tượng có một bộ đếm tham chiếu. Khi có một tham chiếu mới trỏ tới, bộ đếm tăng lên; khi tham chiếu bị hủy, bộ đếm giảm. Nếu bộ đếm về 0, đối tượng được coi là rác và giải phóng ngay. Phương pháp này đơn giản, không cần quét toàn bộ heap, nhưng không xử lý được tham chiếu vòng (circular reference) – hai đối tượng trỏ lẫn nhau nhưng không còn ai dùng, bộ đếm không bao giờ về 0.
Mark and Sweep (Đánh dấu và quét)
Đây là nền tảng của nhiều GC hiện đại. Gồm hai pha: pha đánh dấu duyệt từ root set, đánh dấu tất cả đối tượng còn sống. Pha quét duyệt toàn bộ heap, thu hồi vùng nhớ của các đối tượng không được đánh dấu. Nhược điểm là có thể gây phân mảnh bộ nhớ và cần thời gian tạm dừng toàn bộ ứng dụng.
Copying Collection (Sao chép)
Heap được chia thành hai vùng: vùng hoạt động và vùng dự phòng. GC sao chép các đối tượng còn sống từ vùng hoạt động sang vùng dự phòng, nén chúng lại. Vùng hoạt động cũ trở thành vùng dự phòng và được coi là trống. Phương pháp này giảm phân mảnh, nhưng lãng phí bộ nhớ do luôn cần một vùng trống gấp đôi.
Generational Collection (Thế hệ)
Dựa trên quan sát thực nghiệm: hầu hết đối tượng chết rất sớm (infant mortality). Heap được chia thành các thế hệ: Young, Old và Permanent (hay Metaspace). GC trẻ (Minor GC) quét thường xuyên vùng Young – nơi sinh ra đối tượng mới, đối tượng sống qua vài chu kỳ sẽ được thăng cấp lên Old. GC chính (Major GC) quét cả Old khi cần. Phương pháp này tối ưu hiệu năng vì tập trung vào vùng có nhiều rác nhất.
Comparison of Garbage Collection Algorithms
| Thuật toán | Ưu điểm | Nhược điểm | Ứng dụng điển hình |
|---|---|---|---|
| Reference Counting | Dễ triển khai, thu hồi tức thời | Không xử lý tham chiếu vòng | Python (kết hợp với generational), Swift |
| Mark and Sweep | Xử lý được tham chiếu vòng, không lãng phí vùng nhớ | Gây phân mảnh, tạm dừng lâu | Ruby, Lua |
| Copying Collection | Nén bộ nhớ, không phân mảnh | Tốn bộ nhớ gấp đôi | Hầu hết JVM thế hệ trẻ |
| Generational Collection | Hiệu suất cao, giảm tạm dừng | Phức tạp, cần tinh chỉnh kích thước thế hệ | JVM (HotSpot),.NET |
Lợi ích của Garbage Collection đối với lập trình viên

GC giải phóng lập trình viên khỏi việc cấp phát và giải phóng bộ nhớ thủ công. Điều này giảm đáng kể lỗi như use-after-free, double-free hay rò rỉ bộ nhớ kinh điển. Nhờ GC, năng suất phát triển tăng lên vì lập trình viên tập trung vào logic nghiệp vụ thay vì quản lý tài nguyên cấp thấp. Đặc biệt trong các ứng dụng phức tạp như web server, game engine hay ứng dụng di động, GC giúp hệ thống vận hành ổn định hơn khi phải xử lý hàng triệu đối tượng mỗi giây.
Hạn chế và thách thức khi sử dụng Garbage Collection
GC không phải là giải pháp vạn năng. Nó tiêu tốn thêm CPU và bộ nhớ để chạy chính nó. Những lần dừng toàn bộ chương trình (stop-the-world) có thể gây giật lag trong ứng dụng thời gian thực hoặc game. Ngoài ra, GC có thể gây ra hiện tượng “chồng rác” – nếu ứng dụng tạo nhiều đối tượng tạm thời quá nhanh, GC không dọn kịp, dẫn đến tràn heap. Điều này thường xảy ra khi lập trình viên không tối ưu việc cấp phát đối tượng, ví dụ tạo vô số string trong vòng lặp.
So sánh Garbage Collection và quản lý bộ nhớ thủ công

| Tiêu chí | Garbage Collection | Quản lý thủ công (malloc/free) |
|---|---|---|
| Độ phức tạp lập trình | Thấp – tự động | Cao – lập trình viên tự quản |
| Rủi ro lỗi | Rò rỉ bộ nhớ hiếm (nếu có tham chiếu không mong muốn) | Use-after-free, double-free, memory leak phổ biến |
| Hiệu năng | Thêm overhead tạm dừng | Chi phí gần như không đáng kể |
| Khả năng kiểm soát | Thấp – lập trình viên khó can thiệp thời điểm dọn | Cao – kiểm soát hoàn toàn |
| Phù hợp | Ứng dụng doanh nghiệp, web, prototype | Hệ thống nhúng, kernel, game performance cao |
Ứng dụng thực tế của Garbage Collection trong các ngôn ngữ phổ biến
Garbage Collection trong Java (JVM HotSpot)
JVM cung cấp nhiều bộ thu gom: Serial, Parallel, CMS, G1 và ZGC (low-latency). G1 là mặc định từ Java 9, chia heap thành nhiều vùng nhỏ và ưu tiên dọn vùng chứa nhiều rác nhất. ZGC và Shenandoah hướng đến thời gian tạm dừng dưới 10ms, phù hợp với ứng dụng real-time.
Garbage Collection trong.NET (CLR)
.NET sử dụng generational collector với 3 thế hệ (Gen0, Gen1, Gen2). Gen0 xảy ra thường xuyên nhất, thu dọn các đối tượng tồn tại ngắn. GC trong.NET có chế độ workstation và server, server sử dụng nhiều luồng song song để tăng thông lượng.
Garbage Collection trong Python (CPython)
CPython chủ yếu dùng reference counting kết hợp với generational collector để xử lý tham chiếu vòng. Mỗi đối tượng có một bộ đếm; khi về 0, đối tượng được giải phóng ngay. Điều này khiến Python có độ trễ dọn rác ngắn nhưng chi phí quản lý tham chiếu cao hơn.
Garbage Collection trong Go
Go sử dụng concurrent mark-sweep, cho phép GC chạy song song với chương trình chính mà không cần stop-the-world kéo dài. Tuy nhiên, GC trong Go được tinh chỉnh để giảm latency hơn là throughput tối đa, phù hợp với microservices và server network.
Sai lầm thường gặp khi làm việc với Garbage Collection và cách tránh

Lưu ý quan trọng khi tối ưu ứng dụng liên quan đến Garbage Collection
Khi ứng dụng bị chậm do GC, cần phân tích log GC trước. Các tham số như kích thước heap, số lượng đối tượng thăng cấp, thời gian tạm dừng là manh mối quan trọng. Dùng công cụ như VisualVM, jstat, dotMemory, hoặc perfmon để giám sát. Điều chỉnh kích thước thế hệ và chọn bộ thu gom phù hợp với đặc thù workload. Ví dụ: ứng dụng real-time chọn ZGC hoặc Low-Latency GC; batch processing chọn Parallel GC để tối đa throughput.
FAQ về Garbage Collection

Garbage collection có làm chậm ứng dụng không?
Có, nhưng mức độ phụ thuộc vào thuật toán và cách cấu hình. Các GC hiện đại như G1, ZGC,.NET GC đã tối ưu để giảm tạm dừng xuống dưới vài mili giây. Ngay cả Java 21 với Generational ZGC còn giúp tạm dừng cực ngắn.
Có thể tắt garbage collection được không?
Không thể tắt hoàn toàn trong hầu hết ngôn ngữ quản lý bộ nhớ tự động. Tuy nhiên, có thể giảm thiểu tác động bằng cách tinh chỉnh GC flags hoặc dùng bộ thu gom đặc biệt như Epsilon (Java) – chỉ cấp phát mà không dọn, phù hợp cho ứng dụng chạy ngắn hạn hoặc benchmark.
Garbage collection trong C++ có không?
C++ không có garbage collection mặc định. Lập trình viên tự quản lý bộ nhớ bằng new/delete hoặc smart pointer (std::shared_ptr, std::unique_ptr). Có thể tích hợp thư viện GC ngoài như Boehm GC, nhưng ít phổ biến vì mất kiểm soát tài nguyên.
Làm sao biết ứng dụng đang gặp vấn đề do garbage collection?
Dấu hiệu: ứng dụng bị “giật” không lý do, CPU tăng đột biến theo chu kỳ, thời gian phản hồi chậm. Xem log GC: nếu GC liên tục (hàng trăm lần/phút) và thời gian tạm dừng >100ms, cần xem xét lại việc cấp phát đối tượng hoặc tăng kích thước heap.
Kết luận
Garbage collection là một trong những thành tựu quan trọng của kỹ thuật phần mềm, giúp lập trình viên tránh được vô số lỗi bộ nhớ và tăng năng suất. Hiểu rõ garbage collection là gì và hoạt động ra sao giúp bạn xây dựng ứng dụng ổn định, hiệu quả. Dù có nhược điểm về overhead thời gian chạy, nhưng lợi ích mà GC mang lại vượt trội hơn hẳn trong hầu hết ứng dụng hiện đại. Khi gặp vấn đề hiệu năng, thay vì đổ lỗi cho GC, cần phân tích đúng nguyên nhân và điều chỉnh thiết kế code hoặc cấu hình runtime.
{“@context”:”https://schema.org”,”@type”:”Article”,”headline”:”garbage collection là gì”,”articleSection”:”General”,”keywords”:”garbage collection là gì”,”datePublished”:”2026-06-30T21:09:07+07:00″,”dateModified”:”2026-06-30T21:09:07+07:00″}







