12/08/2018, 14:21

How References work in Java and Android

Trong Java, GC (Garbage Collector) là chương trình chạy nền, làm nhiệm vụ theo dõi các đối tượng trong bộ nhớ, và tiến hành thu hồi bộ nhớ (quá trình Garbage Collection) của các đối tượng khi chúng không còn được tham chiếu đến. Developer cần nắm biết khi nào đối tượng được xem là thỏa mãn điều ...

Trong Java, GC (Garbage Collector) là chương trình chạy nền, làm nhiệm vụ theo dõi các đối tượng trong bộ nhớ, và tiến hành thu hồi bộ nhớ (quá trình Garbage Collection) của các đối tượng khi chúng không còn được tham chiếu đến. Developer cần nắm biết khi nào đối tượng được xem là thỏa mãn điều kiện để GC thu hồi, bởi chúng ta không hề mong muốn các đối tượng không cần thiết được lưu giữ trong bộ nhớ. Trong bài viết này, chúng ta sẽ cùng tìm hiểu thêm về Reference (tạm dịch là tham chiếu) trong Java nói chung và Android nói riêng.

Khái niệm

A reference is the direction of an object that is annotated, so you can access it.

tạm dịch là:

Một tham chiếu chỉ đến một đối tượng được khai báo, nhờ đó ta có thể truy cập được nó.

Phân loại

Trong Java, Reference được chia làm 4 loại là:

  • Strong reference (tạm dịch: tham chiếu mạnh)
  • Weak reference (tạm dịch: tham chiếu yếu)
  • Soft reference (tạm dịch: tham chiếu mềm)
  • Phantom reference (tạm dịch: tham chiếu ma)

Chúng ta sẽ lần lượt đi qua từng loại reference này.

Strong reference

Là loại tham chiếu mặc định, và thường gặp trong Java. Khi tạo một đối tượng thì mặc định một Strong reference được tạo ra bên trong đối tượng.

MyObject obj = new MyObject();

Một đối tượng sẽ không bị GC thu hồi nếu như có bất cứ một chuỗi Strong reference nào liên kết với nó.

public class StrongRefDemo {
    static class MyObject {
        @ Override
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println("I'm collected!"); // will be printed if  MyObject is collected by GC
        }
    }
    static MyObject obj;
    public static void main(String[] args) throws InterruptedException {
        System.out.println("Start");
        obj = new MyObject(); // New strong reference is created.
        obj = null; // To remove strong reference from obj
        System.gc(); // Force to call Garbage collector
        Thread.sleep(5000); // Wait GC finish its job
        System.out.println("End");
    }
}

Trong ví dụ trên, đối tượng obj mất đi Strong reference sau khi gán =null nên thỏa mãn điều kiện để GC thu hồi bộ nhớ (dòng I'm collected! được in ra trong log).

Note:

Trong java, hàm finalize() được GC gọi trên đối tượng khi GC nhận thấy rằng không còn một tham chiếu nào tới đối tượng đó.

strongRef.png

Xét ví dụ tiếp sau đây:

public static void main(String args[]) throws InterruptedException {
        System.out.println("Start");
        obj = new MyObject();
        List<MyObject> list = new ArrayList<MyObject>();
        list.add(obj);
        obj = null;
        System.gc();
        Thread.sleep(5000);
        System.out.println("End");
    }

Trong trường hợp này, đối tượng obj tuy gán =null. Nhưng trước đó, nó đã được thêm vào trong list nên sau khi gán null, nó vẫn là 1 Strongly reachable vì tồn tại 1 đối tượng có tham chiếu đến nó. Do vậy, đối tượng obj sẽ không bị thu hồi.

Để GC có thể thu hồi obj ta cần hủy các tham chiếu đến nó bằng cách gán list = null hoặc list.clear().

Lấy 1 ví dụ thường thấy trong android:

public class MainActivity extends Activity {
    @ Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        new MyAsyncTask().execute();
    }

    private class MyAsyncTask extends AsyncTask {
        @ Override
        protected Object doInBackground(Object[] params) {
            return doSomeStuff();
        }
        private Object doSomeStuff() {
            //do something to get result
            return new MyObject();
        }
    }
}

Trong đoạn code này đối tượng MyAsyncTask có Strong reference với MainActivity, theo đó có 1 vấn đề nảy sinh khi MainActivity bị hủy (onDestroy) và cần được thu hồi bộ nhớ, lúc này giả sử MyAsyncTask vẫn đang thực thi và giữ tham chiếu đến MainActivity, thì điều này làm cho GC không thể thu hồi bộ nhớ của activity, dẫn đến tình trạng leak memory.

WeakReference

Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed.

tạm dịch (+ thêm bớt             </div>
            
            <div class=

0