Garbage Collector

Chúng tôi rất vui mừng chia sẻ kiến thức về từ khóa Garbage la gi để tối ưu hóa nội dung trang web và tiếp thị trực tuyến. Bài viết cung cấp phương pháp tìm kiếm, phân tích từ khóa và chiến lược hiệu quả. Cảm ơn sự quan tâm và hãy tiếp tục theo dõi để cập nhật kiến thức mới.

Nếu bạn đã quen thuộc với việc cấp phát bộ nhớ trong các ngôn ngữ lập trình, bạn sẽ biết rằng có hai phần trong bộ nhớ được định nghĩa là Heap và Stack.

Bạn Đang Xem: Garbage Collector

Bộ nhớ Stack được sử dụng để thực thi trong một luồng. Khi mỗi một function được gọi, một khối bộ nhớ được cấp phát trong stack để lưu trữ các biến cục bộ function đó. Bộ nhớ được phân bổ sẽ đượcgiảti phóng khi kết thúc hàm. Trái ngược với Stack, bộ nhớ Heap được sử dụng để cấp phát động (thường là khi tạo ra các đối tượng mới với từ khóa là new hoặc malloc ) và việc xử lý các bộ nhớ được cấp phát được xử lý riêng.

public void main() { // 1 Create reference Object myObject = new Object(); …… // 2. Remove reference myObject = null }

Nếu tại một thời điểm vào đó của chương trình, có một tham chiếu khác tới object (hay nói cách khác t gán giá trị của myObject tới một giá trị khác) hoặc một giá trị null đựoc gán cho object đó (như trên) thì tham chiếu tồn tới với đối tượng người sử dụng vừa tạo ra sẽ tiến hành xóa (step 2 hình phía bên dưới)

Tuy nhiên bộ nhớ đựoc phân bổ cho đối tượng người sử dụng này còn có thể không đựoc phóng thích mặc dù đối tuợng này còn có thể không được sử dụng. Trong các tiếng nói lập trình cũ hơn như C hoặc là C++, lập trìnhh viên cần quan tâm tới các loại đối tượng người sử dụng được phân bổ trong HEAP và xóa chúng khi không còn được sử dụng để phóng thích bộ nhớ. Không làm điều này còn có thể gây ra rò rỉ bộ nhớ (memoryleak nhiều bạn nhầm điều này với out of memory lắm 🤣🤣🤣🤣🤣🤣)

Mặc khác nếu tất cả chúng ta xóa nhầm có thể dẫn đến lỗi NullPointerExeption

Tuy nhiên, trong các tiếng nói lập trình như Java hay C# việc quản lý bộ nhớ này được thực hiện một cách tự động hóa và riêng biệt thông qua Garbage Collector

Khi có Garbage Collector, tất cả chúng ta có thể cấp phép bộ nhớ cho một đối tượng người sử dụng sau đó sử dụng nó và khi không còn bất kì một tham chiếu nào tới đối tượng người sử dụng đó, đối tượng người sử dụng sẽ tiến hành ghi lại để Garbage Collector phóng thích các bộ nhớ đã được phân bổ. Và Garbage collector cũng đảm nói rằng mọi đối tượng người sử dụng có tham chiếu trực tiếp sẽ không còn bị xóa khỏi bộ nhớ.

Gargabe Collection sẽ theo dõi số lượng th am chiếu cho một đối tượng người sử dụng cụ thể trong bộ nhớ. Cùng tham khảo đoạn code sau

Object a = new Object(); // Reference Count(OB1) starts at 1 Object b = a; // Reference Count (OB1) incremented to 2 as a new reference is added Object c = new Object(); b.someMethod(); b = null; // Reference Count(OB1) decremented to 1 as reference goes away a = c; // Reference Count(OB1) decremented to 0

  1. Khi thực hiện dòng lệnh trước tiên Object a = new Object ();, một đối tượng người sử dụng mới (tạm gọi là OB1) đã được khởi tạo trong bộ nhớ và số lượng reference tới đối tượng người sử dụng này được tính bằng 1.
  2. Đi tới dòng lệnh số 2 Object b = a; lúc này reference của đối tượng người sử dụng a được copy sang đối tượng người sử dụng b, lúc này cả a và b cùng reference tới OB1. Lúc này reference count của OB1 tăng lên thành 2.
  3. Khi b đựoc gán bằng null, lúc này số luợng reference count giảm đi 1, lúc này chỉ từ duy nhất biến a đang reference tới OB1.
  4. Khi biến a được reference tới một địa chỉ ô nhớ khác a = c; lúc này reference count của OB1 = 0, lúc này OB1 đã sẵn sàn được thu dọn bởi Garbage Collection

Xem Thêm : 3 Trường Hợp Cần Phục Hồi Da Càng Sớm Càng Tốt

Nhược điểm chính của Reference Counted trong Garbage Collection là không có khả năng xác định các tham chiếu vòng. Để hiểu thế nào là tham chiếu vòng chúng t a cùng xem đoạn code trong tương lai

Xét 2 lớp A và B có reference tới lớp sót lại

class A { private B b; public void setB(B b) { this.b = b; } } class B { private A a; public void setA(A a) { this.a = a; } }

Hiện giờ trong phương thức main tất cả chúng ta có thể tạo các đối tượng người sử dụng mới cho 2 class này và gán các tham chiếu cho chúng

public class Main { public static void main(String[] args) { A one = new A(); B two = new B(); // Make the objects refer to each other (creates a circular reference) one.setB(two); two.setA(one); // Throw away the references from the main method; the two objects are // still referring to each other one = null; two = null; } }

Khi tất cả chúng ta gán giá trị null cho 2 biến one và two, các tham chiếu bên phía ngoài tồn tại khi đối chiếu với đối tượng người sử dụng class (A và B) đựoc tạo thuở đầu sẽ bị xóa. Tuy nhiên chúng vẫn chưa đủ nhập cuộc để Garbage Collector thu dọn rác vì đối tượng người sử dụng one vẫn còn reference tới đối tượng người sử dụng two thông qua method setB(two); và trái lại cho biến two . Điều này dẫn đến biến one và two sẽ không còn bao giờ bị phóng thích.

1. Mark and Sweep GC

Garbage Collection hoạt động dựa trên 2 thời đoạn chính. Mark and Sweep.

  1. Mark Phase (Thời đoạn ghi lại)
  2. Sweep Phase (Thời đoạn quét)

Mark Phase

Trong thời đoạn này, Garbage Collector xác định các đối tượng người sử dụng vẫn đang sử dụng và ghi lại “mark bit” của chúng thành true. Việc tìm kiếm khai mạc với một tập hợp gốc các tham chiếu được giữ trong các biến cục bộ trong Stack, hoặc biến toàn cục. Khởi nguồn từ các tham chiếu gốc, Garbage Collector sẽ tiến hành tìm kiếm sâu cho những đối tượng người sử dụng có reference tới các gốc này, bất kì đối tượng người sử dụng nào giữ reference tới đối tượng người sử dụng khác, GC giữ cho đối tượng người sử dụng đó tồn tại.

Điều quan trọng cần lưu ý là trong thời đoạn Mark Phase, các luồng ứng dụng cần được tạm ngưng để tránh những thay đổi có thể xẩy ra với trạng thái của đối tượng người sử dụng trong thời đoạn đánh giấu này

Các tham chiếu vòng không phải là vấn đề khi đối chiếu với Mark and Sweep, nếu khách hàng theo dõi diagram trên, có một tham chiếu vòng được biểu thị bằng hình vuông nhưng nó không thể truy cập trực tiếp được từ root, do đó nhưng loại references này sẽ không đựoc ghi lại là đang tồn tại và được chấp nhận GC thu thập như một tài nguyên rác

Sweep Phase

Thời đoạn quyét, tất cả những đối tượng người sử dụng không được ghi lại từ thời đoạn Mark sẽ bị xóa khỏi bộ nhớ, phóng thích không gian của HEAP.

Như các chúng ta có thể theo dõi trên diagram, có thjeer có nhiều vùng tự do sau thời đoạn quét (đựoc vẽ bằng white color). Nhưng do sự phân mảnh này, việc cấp phép bộ nhớ tiếp theo có thể thất bại nếu nó cần nhiều bộ nhớ hơn vùng tự do sót lại. Để giải quyết và xử lý vấn đề này, GC đã add thêm một phase mới, Compact Phase

2. Mark-Sweep-Compact GC

Sau thời đoạn quét, tất cả những vị trí bộ nhớ đựoc xắp xếp lại để cung cấp phân bổ bộ nhớ nhỏ gọn hơn. Nhược điểm của phuơng pháp này là thời kì tạm dừng GC tăng lên vì nó cần sao chếp tất cả những đối tượng người sử dụng sang một địa điểm mới và update tất cả những tham chiếu tới các đối tượng người sử dụng đó

3. Mark and Copy GC

Điều này tuơng tự như cách Mark and Sweep, nhưng không gian bộ nhớ được chia thành hai phần, thuở đầu các đối tượng người sử dụng đựoc phân bổ cho một vùng không gian (như trên hình là fromspace) và các đối tuợng tồn tại được ghi lại (màu xanh 1 2 3 4)

Xem Thêm : Bet on me là gì

Không như thời đoạn Sweep thời đoạn thứ hai là Copy, các đối tượng người sử dụng đựoc ghi lại sẽ tiến hành sao chép vào vùng không gian khác (như trên hình là tospace) và song song được nén lại. Sau đó vùng (fromspace) sẽ bị xóa đi.

Sau quá trình này, cả hai không gian được hoán đổi lẫn nhau.

4. Generational Garbage Collector.

Trong Generational Garbage Collector không gian bộ nhớ chia thành các thế hệ khác nhau (ví dụ Young and Old Generation). Thuở đầu tất cả những đối tượng người sử dụng sẽ tiến hành cấp phép trên Young Generation, tuy nhiên khi một chu kỳ luân hồi thu dọn rác xẩy ra, các đối tượng người sử dụng sống sót sẽ tiến hành chuyển lên Old Generation.

Hiện giờ các đối tượng người sử dụng sót lại trong Yound Generation có thể bị xóa suy bì tất cả những đối tượng người sử dụng sống sót đã được chuyển qua Old Genreration.

Chu kỳ luân hồi thu dọn rác ở Old Generation xẩy ra ít thường xuyên hơn so với thế hệ Young Generation, Ý tuơng đằng sau phuơng pháp này là các đối tuợng sống sót trong lần thu thập rác trước tiên có xu hướng vạn thọ hơn. Do đó tần suất thu gom rác có thể giảm cho những đối tượng người sử dụng Old Generation. Số luơng Generation khác nhau khi đối chiếu với từng tiếng nói lập trình.

Trong android sử dụng cách dọn rác thứ 4 Generational Garbage Collector. Các đối tượng người sử dụng được phân bổ mới sẽ thuộc về Young Generation. Khi một đối tượng người sử dụng hoạt động đủ lâu, nó có thể được thăng cấp lên older generation và cuối cùng là Permanent Generation.

Mỗi thế hệ heap có giới hạn trên dành riêng cho số lượng bộ nhớ mà các đối tượng người sử dụng ở đó có thể chiếm. Bất luận khi nào một thế hệ khai mạc lấp đầy, khối hệ thống sẽ thực hiện một sự kiện thu gom rác nhằm phóng thích bộ nhớ. Thời lượng của cục sưu tập rác phụ thuộc vào thế hệ của những đối tượng người sử dụng mà nó thu thập và số lượng đối tượng người sử dụng hoạt động trong mỗi thế hệ.

Trên đây là những thông tin về Garbage Collector và Garbage Collector trong Android. Rất cảm ơn các bạn đã đón đọc

[1] https://medium.com/@kasunpdh/garbage-collection-how-its-done-d48135c7fe77

[2] https://app.pluralsight.com/library/courses/understanding-java-vm-memory-management/table-of-contents

[3] https://www.geeksforgeeks.org/mark-and-sweep-garbage-collection-algorithm/

[4] https://blogs.msdn.microsoft.com/abhinaba/2009/01/30/back-to-basics-mark-and-sweep-garbage-collection/

[5] https://plumbr.io/handbook/garbage-collection-algorithms

[5] https://developer.android.com/topic/performance/memory-overview#gc

You May Also Like

About the Author: v1000