Bộ Thu Gom Rác
(Garbage Collection)

Trong Java, "garbage" (rác) đề cập đến các đối tượng không còn được tham chiếu.

Garbage Collection là quá trình thu hồi tự động vùng nhớ không sử dụng trong runtime. Nói cách khác, đây là cách để hủy các đối tượng không còn sử dụng.

Trước đây, trong ngôn ngữ C, chúng ta sử dụng hàm free() và trong C++ chúng ta dùng delete() để thực hiện việc này. Nhưng trong Java, quá trình này được thực hiện tự động, giúp quản lý bộ nhớ tốt hơn.

Lợi ích của Garbage Collection:

↳ Hiệu quả bộ nhớ: Garbage collector giúp Java sử dụng bộ nhớ hiệu quả hơn bằng cách loại bỏ các đối tượng không còn được tham chiếu khỏi bộ nhớ heap.

↳ Tự động: Quá trình này được thực hiện tự động bởi garbage collector (một phần của JVM), vì vậy chúng ta không cần phải tốn công sức thêm.

Làm thế nào để một đối tượng không còn được tham chiếu?

Có nhiều cách để một đối tượng trở thành không được tham chiếu:

1. Đặt giá trị tham chiếu về null:

Khi bạn đặt một tham chiếu về null, đối tượng đó sẽ không còn được tham chiếu nữa.

Ví dụ

Employee e = new Employee();  
e = null;  

2. Gán một tham chiếu cho một đối tượng khác:

Khi bạn gán một tham chiếu cho một đối tượng khác, tham chiếu ban đầu sẽ bị mất và đối tượng cũ sẽ không còn được tham chiếu.

Ví dụ

Employee e1 = new Employee();  
Employee e2 = new Employee();  
e1 = e2; // giờ đối tượng đầu tiên mà e1 tham chiếu sẽ có thể bị thu gom rác   

3. Sử dụng đối tượng ẩn danh:

Khi đối tượng được tạo ra nhưng không được gán cho bất kỳ tham chiếu nào, nó sẽ trở thành không được tham chiếu sau khi thực hiện xong tác vụ.

Ví dụ

new Employee();  

Phương thức finalize()

Phương thức finalize() trong Java được sử dụng để thực hiện các công việc dọn dẹp trước khi một đối tượng bị thu gom rác (garbage collected). Đây là một phương thức được định nghĩa trong lớp Object mà tất cả các lớp Java kế thừa từ đó đều có sẵn.

Cú pháp

protected void finalize() throws Throwable {
    // Xử lý dọn dẹp trước khi đối tượng bị thu gom rác
    super.finalize();
}

Cách hoạt động của phương thức finalize():

↳ Gọi finalize(): Phương thức finalize() được gọi tự động bởi garbage collector trước khi đối tượng bị thu gom. Nó cho phép bạn thực hiện các công việc như đóng tệp, giải phóng tài nguyên, hoặc làm sạch các đối tượng liên kết mà đối tượng đang sở hữu.

Lưu ý khi sử dụng phương thức finalize():

↳ Không đảm bảo thời điểm: Bạn không thể dự đoán chính xác khi nào phương thức finalize() sẽ được gọi, vì nó phụ thuộc vào garbage collector. Do đó, không nên phụ thuộc vào phương thức finalize() cho việc giải phóng tài nguyên quan trọng.

↳ Hiệu suất: Sử dụng phương thức finalize() có thể ảnh hưởng đến hiệu suất của ứng dụng do việc garbage collection có thể bị trì hoãn.

↳ Thay thế finalize(): Từ Java 9 trở đi, phương thức finalize() không còn được khuyến khích sử dụng và đã được thay thế bằng các cơ chế khác như try-with-resources và các lớp thực thi AutoCloseable để quản lý tài nguyên.

Phương thức gc()

Phương thức gc() trong Java được sử dụng để yêu cầu garbage collector (GC) thực hiện việc thu gom rác ngay lập tức. Phương thức này có thể được gọi từ các lớp System hoặc Runtime. Tuy nhiên, việc gọi phương thức gc() không đảm bảo rằng garbage collector sẽ ngay lập tức thực hiện việc thu gom; nó chỉ là một gợi ý cho JVM rằng đã đến lúc thực hiện thu gom rác.

Cú pháp

public static void gc() {}

Lưu ý quan trọng khi sử dụng phương thức gc():

↳ Gọi phương thức gc() không đảm bảo rằng garbage collector sẽ chạy ngay lập tức. JVM có thể quyết định thực hiện thu gom rác vào một thời điểm khác dựa trên các yếu tố như mức sử dụng bộ nhớ và chính sách garbage collection hiện tại.

↳ Phương thức gc() chỉ là một gợi ý cho JVM và không yêu cầu thực thi ngay lập tức. Garbage collector có thể chọn không thực hiện ngay lập tức hoặc chọn thời điểm khác để thực hiện.

↳ Garbage collector hoạt động như một luồng daemon trong JVM, và nó thường chạy ở nền, không ảnh hưởng đến các luồng chính của ứng dụng.

Dưới đây là một ví dụ đơn giản để minh họa việc thu gom rác trong Java. Ví dụ này tạo ra một số đối tượng, sau đó yêu cầu garbage collector thu gom rác và chờ đợi một chút để xem kết quả.

Ví dụ: Example.java

public class Example {
    @Override
    protected void finalize() throws Throwable {
        System.out.println("Phương thức finalize() được gọi cho đối tượng: " + this);
        super.finalize(); // Gọi finalize của lớp cha
    }

    public static void main(String[] args) {
        // Tạo một số đối tượng
        Example obj1 = new Example();
        Example obj2 = new Example();
        Example obj3 = new Example();

        // Đặt các tham chiếu về null để chuẩn bị cho việc thu gom rác
        obj1 = null;
        obj2 = null;
        obj3 = null;

        // Yêu cầu garbage collector thực hiện thu gom rác
        System.out.println("Yêu cầu thu gom rác...");
        System.gc();

        // Chờ một chút để garbage collector có thời gian thực hiện
        try {
            Thread.sleep(1000); // Chờ 1 giây
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Yêu cầu thu gom rác đã được thực hiện.");
    }
} 

Kết quả của chương trình là

Yêu cầu thu gom rác...
Phương thức finalize() được gọi cho đối tượng: Example@3e84b737
Phương thức finalize() được gọi cho đối tượng: Example@48f9c5f2
Phương thức finalize() được gọi cho đối tượng: Example@7a3dafdb
Yêu cầu thu gom rác đã được thực hiện.

Các dòng Phương thức finalize() được gọi cho đối tượng: Example@3e84b737 cho biết rằng phương thức finalize() đã được gọi cho các đối tượng bị thu gom rác. Tuy nhiên, hãy lưu ý rằng việc thu gom rác không phải lúc nào cũng xảy ra ngay lập tức khi gọi System.gc().

Câu Nói Truyền Cảm Hứng

“Bắt đầu ở đâu không quan trọng, quan trọng là bạn sẵn sàng bắt đầu.” – W. Clement Stone

Không Gian Tích Cực

“Chúc bạn luôn giữ vững niềm tin và sức mạnh để vượt qua mọi thử thách trong cuộc sống.”