Java – Garbage Collection

Java Garbage Collection là tiến trình chương trình Java quản lý bộ nhớ tự động. Chương trình Java biên dịch thành bytecode có thể được chạy trên máy ảo Java, viết tắt JVM. Khi chương trình Java chạy trên JVM, các Object được tạo trên bộ nhớ Heap, là một phần của bộ nhớ dành riêng cho chương trình. Cuối cùng, một vài Object sẽ không còn cần thiết. Garbage Collection sẽ tìm những Object không sử dụng và xoá chúng để giải phóng bộ nhớ

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

Java Garbage Collection là một tiến trình tự động. Lập trình viên không cần đánh dấu rõ ràng các Object cần xoá. Việc thực thi thu gom rác trực tiếp trong JVM. Mỗi JVM có thể thực hiện thu gom rác tuy nhiên nó làm hài lòng, yêu cầu duy nhất là nó đáp ứng đặc tả của JVM. Mặc dù có rất nhiều JVM, cho đến nay Oracle HotSpot là phổ biến nhất, nó cung cấp một tập hợp mạnh mẽ và kỹ càng cho các lựa chọn thu gom rác.

Mặc dù HotSpot có nhiều tiến trình Garbage Collection được tối ưu cho các trường hợp sử dụng khác nhau, tất cả đều phải theo một cách thức cơ bản. Bước đầu tiên, Object không được tham chiếu được xác định và đánh dấu như là đã sẵn sàng cho việc thu gom rác. Trong bước thứ hai, các Object được đánh dấu được xoá. Tuỳ chọn, bộ nhớ có thể được nén sau khi tiến trình thu gom rác xoá các Object, nên các Object còn lại nằm trong một khối liền kề khi bắt đầu bộ nhớ Heap. Quá trình nén giúp cho việc cấp phát bộ nhớ dễ dàng hơn cho các Object mới theo thời gian sau khi khối bộ nhớ được cấp phát cho các Object hiện tại.

Tất cả các tiến trình thu dọn rác của HotSpot thực hiện chiến lược thu gom rác theo thế hệ, phân loại các Object theo độ tuổi. Lý do đằng sau việc thu gom rác theo thế hệ là vì hầu hết các Object tồn tại trong thời gian ngắn và sẽ sẵn sàng cho việc thu gom rác sớm sau khi tạo ra.

Bộ nhớ Heap được chia làm 3 phần:

  • Young Generation (Thế hệ trẻ): Các Object mới được tạo bắt đầu trong Young Generation. Young Generation được chia nhỏ thành khoảng trống Eden nơi tất cả các Object mới bắt đầu, và 2 khoảng trống Survivor nơi các Object được chuyển từ Eden sau khi tồn tại qua một chu kỳ thu dọn rác. Khi các Object là rác được thu thập từ Young Generation, nó là sự kiện thu gom rác nhỏ.
  • Old Generation (Thế hệ cũ): Các Object tồn tại lâu cuối cùng được chuyển từ Young Generation sang Old Generation. Khi các Object là rác được thu thập từ Old Generation, nó là sự kiện thu gom rác lớn.
  • Permanent Generation (Thế hệ vĩnh cửu): Một siêu dữ liệu như là các class và phương thức được lưu trữ trong Permanent Generation. Các class mà không còn được sử dụng là rác được thu thập từ Permanent Generation.

Trong suốt sự kiện thu gom rác đầy đủ, các Object không sử dụng trong tất cả các thế hệ là rác được thu thập.

HotSpot có 4 tiến trình thu gom rác:

  • Serial (Nối tiếp nhau): Tất cả các sự kiện thu gom rác được điều khiển theo từng chu kỳ trong một tiến trình. Nén được thực hiện sau mỗi tiến trình thu gom rác
  • Parallel (Song song): Các tiến trình chạy đồng thời được sử dụng cho thu gom rác nhỏ. Một tiến trình đơn được sử dụng cho thu gom rác chính và nén Old Generation
  • CMS (Concurrent Mark Sweep – Quét đồng thời): Nhiều tiến trình được sử dụng cho thu thập các rác nhỏ, sử dụng cùng một thuật toán như Parallel. Thu thập các rác chính là chạy đa luồng, giống như Parallel, nhưng CMS chạy đồng thời với tiến trình của ứng dụng để giảm đến mức tối thiểu các sự kiện “stop the world” (Ví dụ khi việc thu gom rác chạy gây dừng ứng dụng). Không thực hiện nén
  • G1 (Garbage First – Rác trước tiên): Tiến trình thu gom rác mới nhất được dự định thay thế cho CMS. Nó chạy song song và đồng thời như CMS, nhưng nó hoạt động hoàn toàn khác so với trình thu gom rác cũ

Ưu điểm

Ưu điểm lớn nhất của Garbage Collection là được điều khiển tự động xoá các Object không sử dụng hay các Object nằm ngoài tầm với để giải phóng tài nguyên bộ nhớ quan trọng. Các lập trình viên làm việc với các ngôn ngữ không có Garbage Collection (như là C hoặc C++) phải thực thi phần quản lý bộ nhớ bằng tay trong code.

Mặc dù yêu cầu thêm việc, một số lập trình viên tranh luận ủng hộ việc quản lý bộ nhớ bằng tay thay vì Garbage Collection, lý do chủ yếu là kiểm soát và hiệu suất. Trong khi việc tranh luận về quản lý bộ nhớ tiếp tục nổ ra, Garbage Collection giờ đây là thành phần tiêu chuẩn của nhiều ngôn ngữ lập trình phổ biến. Đối với các kịch bản nơi các Garbage Collection ảnh hưởng tiêu cực đến hiệu suất, Java đề xuất nhiều lựa chọn để điều chỉnh cho các tiến trình Garbage Collection để cải thiện hiệu quả của nó.

Các bài toán thực tế

Đối với nhiều ứng dụng đơn giản, Java Garbage Collection không phải thứ mà lập trình viên cân nhắc một cách có ý thức. Tuy nhiên, đối với các lập trình viên muốn nâng cao kỹ năng Java, điều quan trọng là phải hiểu cách Java Garbage Collection hoạt động và cách nó có thể được điều chỉnh.

Bên cạnh cơ chế cơ bản của Garbage Collection, một trong những điểm quan trọng nhất của Java Garbage Collection là  nó không mang tính quyết định, và không có cách nào dự đoán khi nào việc dọn dẹp rác xảy ra lúc đang chạy. Có thể bao gồm một gợi ý trong code để chạy tiến trình Garbage Collection bằng phương thức System.gc() hoặc Runtime.gc(), nhưng chúng không cung cấp sự đảm bảo rằng tiến trình Garbage Collection sẽ thực sự chạy.

Cách tiếp cận tốt nhất để điều chỉnh Java Garbage Collection là cài đặt các cờ trên JVM. Các cờ có thể điều chỉnh các tiến trình Garbage Collection được sử dụng (ví dụ Serial, G1…), kích thước khởi tạo và tối đa của bộ nhớ Heap, kích thước các vị trí trong Heap ( như là Young Generation, Old Generation…) và vv… Bản chất của ứng dụng đang được điều chỉnh là một hướng dẫn tốt ban đầu cho cài đặt. Tiến trình Garbage Collection Parallel hiệu suất tốt, nhưng sẽ thường xuyên gây ra “stop the world”, làm cho nó phù hợp với các tiến trình backend sao cho có thể tạm dừng thời gian dài cho việc Garbage Collection.

Mặt khác, tiến trình Garbage Collection CMS được thiết kế để giảm tối đa thời gian dừng, làm cho nó trở nên lý tưởng cho các ứng dụng GUI trong đó khả năng đáp ứng là quan trọng.

Những tinh chỉnh bổ sung có thể được thực hiện bằng cách thay đổi kích thước của bộ nhớ Heap hoặc từng vị trí trong trong bộ nhớ và đo hiệu quả của Garbage Collection sử dụng các công cụ như là jstat.

 

 

You May Also Like

About the Author: Nguyen Dinh Thuc

Leave a Reply

Your email address will not be published.