"Xin chào! Tôi quyết định cho bạn một bài học nhỏ khác về thu gom rác thải."

Như bạn đã biết, máy Java tự giám sát khi một đối tượng trở nên không cần thiết và xóa nó.

"Ừ. Lúc trước ngươi cùng Rishi có nói với ta. Ta không nhớ rõ chi tiết."

"OK. Vậy chúng ta xem lại lần nữa."

Thu gom rác thải - 1

"Ngay sau khi một đối tượng được tạo, JVM sẽ cấp phát bộ nhớ cho nó. Sự quan tâm đến đối tượng được theo dõi bằng cách sử dụng các biến tham chiếu.  Một đối tượng có thể bị xóa trong quá trình thu gom rác, tức là quy trình giải phóng bộ nhớ nếu không có biến nào tham chiếu đến đối tượng đó. đối tượng. "

"Hãy cho tôi biết một chút về bộ thu gom rác—nó là gì và nó hoạt động như thế nào."

"OK. Quá trình thu gom rác từng diễn ra trên luồng chính. Cứ sau 5 phút hoặc thường xuyên hơn. Nếu không có đủ bộ nhớ trống, máy Java sẽ tạm dừng tất cả các luồng và xóa các đối tượng không sử dụng."

"Nhưng cách tiếp cận này hiện đã bị loại bỏ. Trình thu gom rác thế hệ tiếp theo hoạt động đằng sau hậu trường và trên một chuỗi riêng biệt. Đây được gọi là thu gom rác đồng thời."

"Tôi hiểu rồi. Quyết định xóa một đối tượng hay không được đưa ra chính xác như thế nào?"

"Chỉ đếm số tham chiếu đến một đối tượng là không hiệu quả lắm—có thể có các đối tượng tham chiếu lẫn nhau nhưng không được tham chiếu bởi các đối tượng khác."

"Vì vậy, Java có một cách tiếp cận khác.  Java chia các đối tượng thành có thể truy cập và không thể truy cập.  Một đối tượng có thể truy cập (còn sống) nếu nó được tham chiếu bởi một đối tượng có thể truy cập (còn sống) khác. Khả năng tiếp cận được xác định từ các luồng. Các luồng đang chạy luôn được coi là có thể truy cập (còn sống) , ngay cả khi không ai tham khảo chúng."

"OK. Tôi nghĩ tôi hiểu rồi."

"Việc thu gom rác thực tế diễn ra như thế nào—việc xóa các đối tượng không cần thiết?"

"Thật đơn giản. Trong Java, bộ nhớ được chia thành hai phần theo quy ước và khi đến lúc thu gom rác, tất cả các đối tượng sống (có thể truy cập) sẽ được sao chép sang một phần khác của bộ nhớ và tất cả bộ nhớ cũ đều được giải phóng."

"Đó là một cách tiếp cận thú vị. Không cần đếm tham chiếu: sao chép tất cả các đối tượng có thể truy cập và mọi thứ khác là rác."

"Nó phức tạp hơn thế một chút. Các lập trình viên Java nhận thấy rằng các đối tượng thường được chia thành hai loại: tồn tại lâu dài (tồn tại trong suốt thời gian chương trình đang chạy) và tồn tại trong thời gian ngắn (cần thiết trong các phương thức và để thực hiện «cục bộ » hoạt động)."

"Sẽ hiệu quả hơn nhiều nếu tách biệt các vật thể tồn tại lâu dài với những vật thể tồn tại trong thời gian ngắn. Để làm được điều này, cần phải tìm ra cách xác định tuổi thọ của vật thể."

"Vì vậy, họ chia tất cả bộ nhớ thành «thế hệ». Có đối tượng thế hệ thứ nhất, đối tượng thế hệ thứ hai, v.v. Mỗi khi bộ nhớ bị xóa, bộ đếm thế hệ được tăng thêm 1. Nếu một số đối tượng tồn tại trong nhiều thế hệ, thì chúng được ghi nhận là tồn tại lâu dài."

"Ngày nay, trình thu gom rác là một phần rất phức tạp và hiệu quả của Java. Nhiều phần của nó hoạt động theo phương pháp phỏng đoán—dựa trên các thuật toán đưa ra dự đoán. Kết quả là, nó thường «không lắng nghe» người dùng."

"Nghĩa?"

"Java có một đối tượng thu gom rác ( GC ) có thể được gọi bằng phương thức System.gc ()."

"Bạn cũng có thể sử dụng System.runFinalization() để buộc các cuộc gọi đến các phương thức hoàn thiện của các đối tượng sẽ bị xóa. Nhưng thực tế là, theo tài liệu Java, điều này đảm bảo rằng bộ sưu tập rác sẽ không bắt đầu, cũng như việc hoàn thiện ( ) sẽ được gọi.  Bộ thu gom rác quyết định khi nào gọi nó và gọi cái gì. "

"Ồ! Biết thì tốt."

"Nhưng còn nhiều hơn nữa. Như bạn đã biết, trong Java, một số đối tượng tham chiếu đến những đối tượng khác. Mạng tham chiếu này được sử dụng để xác định xem có nên xóa một đối tượng hay không."

"Và, hãy nhìn xem. Java có các tham chiếu đặc biệt cho phép bạn tác động đến quá trình này. Có các lớp trình bao bọc đặc biệt dành cho chúng. Đây là:"

" SoftReference  là một tài liệu tham khảo mềm."

" WeakReference  là một tài liệu tham khảo yếu."

" PhantomReference là một tham chiếu ảo."

"Uh... Điều này làm tôi nhớ đến các lớp bên trong, các lớp lồng nhau, các lớp ẩn danh lồng nhau và các lớp cục bộ. Tên thì khác, nhưng không rõ chúng dùng để làm gì."

"Nói đi, Amigo, bạn đã trở thành một lập trình viên. Bây giờ bạn tức giận vì tên lớp, nói rằng «chúng không đủ thông tin, và không thể với một cái tên (!) để xác định lớp này làm gì, như thế nào, và tại sao"."

"Chà. Tôi thậm chí còn không để ý. Nhưng nó quá rõ ràng."

"OK. Nói đủ rồi. Để tôi kể cho bạn nghe về SoftReferences."

"Những tham chiếu này được thiết kế đặc biệt cho bộ nhớ đệm, mặc dù chúng có thể được sử dụng cho các mục đích khác—tất cả đều theo quyết định của người lập trình."

"Đây là một ví dụ về một tài liệu tham khảo như vậy:"

Ví dụ
// Create a Cat object
Cat cat = new Cat();

// Create a soft reference to a Cat object
SoftReference<Cat> catRef = new SoftReference<Cat>(cat);

// Now only the catRef soft reference points at the object
cat = null;

// Now the ordinary cat variable also references the object
cat = catRef.get();

// Clear the soft reference
catRef.clear();

"Nếu các tham chiếu duy nhất đến một đối tượng là mềm, thì nó sẽ tiếp tục tồn tại và được gọi là 'có thể tiếp cận mềm'."

"Nhưng!  Một đối tượng chỉ được tham chiếu bởi các tham chiếu mềm có thể bị xóa bởi trình thu gom rác nếu chương trình không có đủ bộ nhớ.  Nếu đột nhiên chương trình không có đủ bộ nhớ, trước khi ném OutOfMemoryException , trình thu gom rác sẽ xóa tất cả các đối tượng được tham chiếu bởi các tham chiếu mềm và sẽ thử cấp phát lại bộ nhớ cho chương trình."

"Giả sử một chương trình máy khách thường xuyên yêu cầu nhiều dữ liệu khác nhau từ một chương trình máy chủ. Chương trình máy chủ có thể sử dụng SoftReference để lưu trữ một số dữ liệu đó. Nếu các đối tượng được giữ nguyên bởi các tham chiếu mềm chiếm một phần lớn bộ nhớ, thì trình thu gom rác chỉ cần xóa chúng tất cả. Nó thật đẹp!"

"Ừ. Bản thân tôi thích nó."

"Chà, một bổ sung nhỏ: Lớp SoftReference có hai phương thức. Phương thức get() trả về đối tượng được tham chiếu bởi SoftReference . Nếu đối tượng bị xóa bởi trình thu gom rác, phương thức get () sẽ đột nhiên bắt đầu trả về giá trị rỗng."

"Người dùng cũng có thể xóa SoftReference một cách rõ ràng bằng cách gọi phương thức clear(). Trong trường hợp này, liên kết yếu bên trong đối tượng SoftReference sẽ bị hủy."

"Đó là tất cả cho bây giờ."

"Cảm ơn vì câu chuyện thú vị, Ellie. Nó thực sự rất thú vị."