Sự khác biệt giữa SoftReference và WeakReference trong Java là gì?


811

Sự khác biệt giữa java.lang.ref.WeakReferencevà là java.lang.ref.SoftReferencegì?


9
SoftReferences là loại (không thực sự nhưng vì mục đích thảo luận) WeakReferences thường được thu thập khi JVM nghĩ rằng nó hết bộ nhớ.
Ajeet Ganga

5
@AjeetGanga, Loose refs luôn được thu thập bất cứ khi nào GC chạy. Xem stackoverflow.com/a/46291143/632951
Pacerier

Câu trả lời:


927

Từ việc hiểu các tài liệu tham khảo yếu , bởi Ethan Nicholas:

Tài liệu tham khảo yếu

Một tham chiếu yếu , đơn giản chỉ là, một tham chiếu không đủ mạnh để buộc một đối tượng ở lại trong bộ nhớ. Tài liệu tham khảo yếu cho phép bạn tận dụng khả năng của người thu gom rác để xác định khả năng tiếp cận cho bạn, vì vậy bạn không phải tự làm điều đó. Bạn tạo một tài liệu tham khảo yếu như thế này:

WeakReference weakWidget = new WeakReference(widget);

và sau đó ở nơi khác trong mã bạn có thể sử dụng weakWidget.get()để lấy Widgetđối tượng thực tế . Tất nhiên, tham chiếu yếu không đủ mạnh để ngăn chặn việc thu gom rác, vì vậy bạn có thể tìm thấy (nếu không có tham chiếu mạnh đến tiện ích) weakWidget.get()đột nhiên bắt đầu quay lại null.

...

Tài liệu tham khảo mềm

Một tài liệu tham khảo mềm giống hệt như một tài liệu tham khảo yếu, ngoại trừ việc nó ít háo hức vứt bỏ đối tượng mà nó đề cập đến. Một đối tượng chỉ có thể tiếp cận yếu (tham chiếu mạnh nhất đến nó WeakReferences) sẽ bị loại bỏ ở chu kỳ thu gom rác tiếp theo, nhưng một đối tượng có thể tiếp cận nhẹ thường sẽ tồn tại trong một thời gian.

SoftReferenceskhông bắt buộc phải cư xử khác hơn WeakReferences, nhưng trong thực tế, các vật thể có thể tiếp cận nhẹ thường được giữ lại miễn là bộ nhớ được cung cấp dồi dào. Điều này làm cho chúng trở thành một nền tảng tuyệt vời cho bộ đệm, chẳng hạn như bộ đệm hình ảnh được mô tả ở trên, vì bạn có thể để bộ thu gom rác lo lắng về cả hai đối tượng có thể tiếp cận như thế nào (một đối tượng có thể tiếp cận mạnh sẽ không bao giờ bị xóa khỏi bộ đệm) và nó tệ đến mức nào cần bộ nhớ họ đang tiêu thụ.

Và Peter Kessler đã thêm vào một bình luận:

Sun JRE đối xử với SoftReferences khác với WeakReferences. Chúng tôi cố gắng giữ đối tượng được tham chiếu bởi SoftReference nếu không có áp lực lên bộ nhớ khả dụng. Một chi tiết: chính sách dành cho JRE "-client" và "-server" là khác nhau: JRE -client cố gắng giữ dấu chân của bạn nhỏ bằng cách thích xóa SoftReferences thay vì mở rộng heap, trong khi JRE của máy chủ cố gắng giữ cho bạn hiệu suất cao bằng cách thích mở rộng vùng heap (nếu có thể) thay vì xóa SoftReferences. Một kích thước không phù hợp với tất cả.


7
Bài viết không có sẵn, bạn có thể tìm thấy nó trên máy Wayback: web.archive.org/web/20061130103858/http://weblogs.java.net/blog/...
riccardo.tasso

lần này, kho lưu trữ không còn nữa
user1506104

209

Tài liệu tham khảo yếu được thu thập háo hức. Nếu GC thấy rằng một đối tượng có thể truy cập yếu (chỉ có thể truy cập thông qua các tham chiếu yếu), nó sẽ xóa các tham chiếu yếu đến đối tượng đó ngay lập tức. Như vậy, chúng tốt cho việc giữ tham chiếu đến một đối tượng mà chương trình của bạn cũng giữ (tham chiếu mạnh mẽ) "thông tin liên quan" theo cách nào đó, như thông tin phản ánh được lưu trong bộ nhớ cache về một lớp hoặc trình bao bọc cho một đối tượng, v.v. không có ý nghĩa gì để giữ sau khi đối tượng mà nó được liên kết là GC-ed. Khi tham chiếu yếu bị xóa, nó sẽ bị mê hoặc trong hàng đợi tham chiếu mà mã của bạn bỏ phiếu ở đâu đó và nó cũng loại bỏ các đối tượng liên quan. Đó là, bạn giữ thêm thông tin về một đối tượng, nhưng thông tin đó không cần thiết một khi đối tượng mà nó đề cập đến biến mất. Thực ra, trong một số trường hợp nhất định, bạn thậm chí có thể phân lớp WeakReference và giữ thông tin bổ sung liên quan về đối tượng trong các trường của lớp con WeakReference. Một cách sử dụng điển hình khác của WeakReference là kết hợp với Bản đồ để giữ các trường hợp chính tắc.

Mặt khác, SoftReferences rất tốt cho việc lưu trữ các tài nguyên bên ngoài, có thể tái tạo vì GC thường trì hoãn việc xóa chúng. Mặc dù được đảm bảo rằng tất cả SoftReferences sẽ bị xóa trước khi OutOfMemoryError bị ném, vì vậy về mặt lý thuyết chúng không thể gây ra OOME [*].

Ví dụ trường hợp sử dụng điển hình là giữ một dạng nội dung được phân tích cú pháp từ một tệp. Bạn sẽ triển khai một hệ thống trong đó bạn tải một tệp, phân tích cú pháp và giữ SoftReference cho đối tượng gốc của biểu diễn được phân tích cú pháp. Lần tới khi bạn cần tệp, bạn sẽ cố truy xuất tệp thông qua SoftReference. Nếu bạn có thể truy xuất nó, bạn đã bỏ qua cho mình một tải / phân tích khác và nếu GC xóa nó trong lúc này, bạn tải lại nó. Bằng cách đó, bạn sử dụng bộ nhớ miễn phí để tối ưu hóa hiệu suất, nhưng không gặp rủi ro OOME.

Bây giờ cho [*]. Giữ một SoftReference không thể tự gây ra một OOME. Mặt khác, nếu bạn sử dụng nhầm SoftReference cho một tác vụ thì WeakReference sẽ được sử dụng (cụ thể là, bạn giữ thông tin được liên kết với một đối tượng nào đó được tham chiếu mạnh mẽ và loại bỏ nó khi đối tượng Tham chiếu bị xóa), bạn có thể chạy vào OOME như mã của bạn thăm dò ReferenceQueue và loại bỏ các đối tượng liên quan có thể xảy ra để không chạy đúng lúc.

Vì vậy, quyết định phụ thuộc vào việc sử dụng - nếu bạn lưu trữ thông tin tốn kém để xây dựng, nhưng dù sao cũng có thể được cấu trúc lại từ dữ liệu khác, hãy sử dụng các tham chiếu mềm - nếu bạn đang giữ một tham chiếu đến một thể hiện chính tắc của một số dữ liệu hoặc bạn muốn có một tham chiếu đến một đối tượng mà không "sở hữu" nó (do đó ngăn không cho nó trở thành GC'd), sử dụng một tham chiếu yếu.


14
Đặc biệt hữu ích cho việc giải thích khi nào các đối tượng yếu sẽ được sử dụng.
Jack BeNimble

Một điểm quan trọng về việc sử dụng đúng cách WeakReferencelà ở những nơi mà người ta nên sử dụng nó, thực tế là người ta có thể vẫn còn hiệu lực trong một thời gian sau khi tham chiếu vượt quá phạm vi có thể được chấp nhận, nhưng không được mong muốn.
supercat

Tôi đang đấu tranh để hiểu việc sử dụng WeakHashMap là gì nếu nó luôn tạo tham chiếu yếu đến đối tượng giá trị chính của nó?

@supercat, Chỉ có một cách sử dụng hợp lý WeakReferencelà quan sát các lần chạy của GC. Xem chi tiết: stackoverflow.com/a/46291143/632951
Pacerier

1
@Pacerier: Tác giả của bài đăng đó đơn giản là sai. Anh ta bỏ qua một số tình huống sử dụng khác như đăng ký sự kiện, điểm thứ hai của anh ta là vô nghĩa, và điểm thứ ba của anh ta cho rằng một lập trình viên có thể làm những việc có thể không thể. Điểm đầu tiên của anh ấy là hợp lý, nhưng quan hệ trực tiếp với những gì tôi nói. Ví dụ, nếu mã sẽ thường xuyên phải xây dựng và so sánh các đối tượng bất biến lớn, thì phần xây dựng thường sẽ rẻ hơn nếu mã tạo ra các đối tượng mới mà không quan tâm đến việc chúng có tồn tại hay không, nhưng so sánh giữa một đối tượng và chính nó (tham chiếu giống hệt nhau) sẽ ...
supercat

155

Trong Java ; thứ tự từ mạnh nhất đến yếu nhất, có: Mạnh, Mềm, Yếu và Phantom

Một tài liệu tham khảo mạnh mẽ là một tài liệu tham khảo bình thường để bảo vệ các đối tượng được gọi từ bộ sưu tập bằng phương pháp GC. tức là không bao giờ rác thu gom.

Một mềm tham khảo là đủ điều kiện cho việc thu thập bằng cách thu gom rác, nhưng có lẽ sẽ không được thu thập cho đến khi bộ nhớ của nó là cần thiết. tức là rác thu gom trước OutOfMemoryError.

Một tài liệu tham khảo Yếu là một tài liệu tham khảo mà không bảo vệ một đối tượng tham chiếu từ bộ sưu tập bằng phương pháp GC. tức là rác thu gom khi không có ref mạnh hay mềm.

Một Phantom tham khảo là một tham chiếu đến một đối tượng được phantomly tham chiếu sau khi nó đã được hoàn tất, nhưng trước khi cấp phát bộ nhớ của nó đã được khai hoang.

Nguồn

Tương tự: Giả sử JVM là một vương quốc, Object là một vị vua của vương quốc và GC là kẻ tấn công của vương quốc, người cố gắng giết vua (đối tượng).

  • Khi King mạnh , GC không thể giết anh ta.
  • Khi King mềm , GC tấn công anh ta nhưng King cai trị vương quốc với sự bảo vệ cho đến khi có sẵn tài nguyên.
  • Khi King yếu , GC tấn công anh ta nhưng cai trị vương quốc mà không được bảo vệ.
  • Khi vua là Phantom , GC đã giết anh ta nhưng vua có sẵn thông qua linh hồn của anh ta.

7
Tài liệu tham khảo mềm ... until memory is availablekhông có ý nghĩa. Ý bạn là is eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another usesao
ToolmakerSteve

1
có, người thu gom rác sẽ không thu thập tài liệu tham khảo cho đến khi bộ nhớ khả dụng.
Premraj

2
Tôi thích những thứ được giải thích đơn giản, không có quá nhiều bla bla bla +1 từ tôi!
Adelin

3
Tóm tắt tuyệt vời với ví dụ sáng tạo
Ravindra babu


77

Tham khảo yếu http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html

Nguyên tắc: weak reference có liên quan đến việc thu gom rác. Thông thường, đối tượng có một hoặc nhiều referencesẽ không đủ điều kiện để thu gom rác.
Nguyên tắc trên không được áp dụng khi có weak reference. Nếu một đối tượng chỉ có tham chiếu yếu với các đối tượng khác, thì đối tượng đó đã sẵn sàng để thu gom rác.

Hãy xem ví dụ dưới đây: Chúng ta có một Mapđối tượng trong đó Key là tham chiếu một đối tượng.

import java.util.HashMap;   
public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> aMap = new 
                       HashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        System.out.println("Size of Map" + aMap.size());

    }
}

Bây giờ, trong quá trình thực hiện chương trình chúng tôi đã thực hiện emp = null. Việc Mapgiữ chìa khóa không có ý nghĩa gì ở đây null. Trong tình huống trên, đối tượng không được thu gom rác.

Bản đồ yếu

WeakHashMaplà một trong đó các mục ( key-to-value mappings) sẽ bị xóa khi không thể truy xuất chúng từ Map.

Hãy để tôi hiển thị ví dụ trên giống với WeakHashMap

import java.util.WeakHashMap;

public class Test {

    public static void main(String args[]) {
        WeakHashMap<Employee, EmployeeVal> aMap = 
                    new WeakHashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        int count = 0;
        while (0 != aMap.size()) {
            ++count;
            System.gc();
        }
        System.out.println("Took " + count
                + " calls to System.gc() to result in weakHashMap size of : "
                + aMap.size());
    }
}

Đầu ra: Lấy 20 calls to System.gc()kết quả aMap sizelà: 0.

WeakHashMapchỉ tham chiếu yếu đến các khóa, không tham chiếu mạnh như các Maplớp khác . Có những tình huống mà bạn phải quan tâm khi giá trị hoặc khóa được tham chiếu mạnh mẽ mặc dù bạn đã sử dụng WeakHashMap. Điều này có thể tránh được bằng cách bọc đối tượng trong WeakReference .

import java.lang.ref.WeakReference;
import java.util.HashMap;

public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> map = 
                      new HashMap<Employee, EmployeeVal>();
        WeakReference<HashMap<Employee, EmployeeVal>> aMap = 
                       new WeakReference<HashMap<Employee, EmployeeVal>>(
                map);

        map = null;

        while (null != aMap.get()) {
            aMap.get().put(new Employee("Vinoth"),
                    new EmployeeVal("Programmer"));
            System.out.println("Size of aMap " + aMap.get().size());
            System.gc();
        }
        System.out.println("Its garbage collected");
    }
}

Tài liệu tham khảo mềm.

Soft Referencemạnh hơn một chút mà tham chiếu yếu. Tham chiếu mềm cho phép thu gom rác, nhưng cầu xin người thu gom rác chỉ xóa nếu không có tùy chọn nào khác.

Trình thu gom rác không tích cực thu thập các đối tượng có thể tiếp cận nhẹ nhàng như cách thực hiện với các đối tượng có thể tiếp cận yếu - thay vào đó, nó chỉ thu thập các đối tượng có thể tiếp cận nhẹ nếu thực sự "cần" bộ nhớ. Tài liệu tham khảo mềm là một cách để nói với người thu gom rác, "Miễn là bộ nhớ không quá chật, tôi muốn giữ vật này xung quanh. Nhưng nếu bộ nhớ trở nên rất chật, hãy tiếp tục và thu thập nó và tôi sẽ giải quyết với." Bộ thu gom rác được yêu cầu xóa tất cả các tham chiếu mềm trước khi có thể ném OutOfMemoryError.


5
Bạn có thể nhận được một NullPointerExceptiontrong aMap.get().put(...).
xehpuk

Ví dụ HashMap đầu tiên của bạn có vẻ sai. Khi bạn thực hiện "aMap.put (emp, val);" cả 'emp' và 'val' đều là những tài liệu tham khảo mạnh mẽ. Trong nội bộ, một biến mới được tạo để giữ 'emp' và 'val' vì vậy khi bạn thực hiện "emp = null;" bạn chỉ vô hiệu hóa biến "emp", nhưng không phải là biến nội bộ đối với bản đồ băm (vẫn đang giữ đối tượng Nhân viên gốc). Do đó, bản đồ băm vẫn sẽ giữ một tham chiếu mạnh mẽ đến 'emp' bất kể bạn làm gì với biến 'emp' bên ngoài.
Tiago

@Tiago. Không. Có lẽ bằng "ví dụ đầu tiên" mà bạn đang đề cập đến WeakHashMapví dụ (vì đó là ví dụ đầu tiên thể hiện hành vi yếu). Xem tài liệu cho "WeakHashMap": "An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. " Toàn bộ quan điểm của việc sử dụng WeakHashMap là bạn không phải khai báo / truyền vào WeakReference; WeakHashMap làm điều đó cho bạn, trong nội bộ. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html
ToolmakerSteve

Đã thực hiện 0 cuộc gọi đến System.gc () để dẫn đến kích thước yếuHashMap của: 0 là đầu ra của chương trình thứ hai của bạn?
Adelin

1
Đối với một ví dụ khác về WeakHashMaphoạt động, với ứng dụng ví dụ chỉ ra cách loại bỏ các mục sau khi thực thi bộ sưu tập rác, hãy xem Câu trả lời của tôi cho câu hỏi, WeakHashMap có phát triển không, hay nó có xóa các khóa rác không? .
Basil Bourque

50

Sự khác biệt thực sự duy nhất giữa một tham chiếu mềm và một tham chiếu yếu là

trình thu gom rác sử dụng các thuật toán để quyết định có thu hồi một đối tượng có thể tiếp cận nhẹ hay không, nhưng luôn lấy lại một đối tượng có thể tiếp cận yếu.


@ATorras, Samir. Tôi đã mở rộng câu trả lời này tại đây: stackoverflow.com/a/46291143/632951
Pacerier

25

SoftReferenceđược thiết kế cho bộ nhớ cache. Khi phát hiện ra rằng một WeakReferencetham chiếu một đối tượng không thể truy cập khác, thì nó sẽ bị xóa ngay lập tức. SoftReferencecó thể để lại như vậy. Thông thường, có một số thuật toán liên quan đến dung lượng bộ nhớ trống và thời gian sử dụng cuối cùng để xác định xem có nên xóa nó hay không. Thuật toán Sun hiện tại là xóa tham chiếu nếu nó không được sử dụng trong nhiều giây vì có megabyte bộ nhớ miễn phí trên heap Java (có thể cấu hình, máy chủ HotSpot kiểm tra đối với heap tối đa có thể được thiết lập bởi -Xmx). SoftReferences sẽ bị xóa trước khi OutOfMemoryErrorném, trừ khi có thể tiếp cận.


9
Nhưng trong Android nó không được khuyến cáo cho bộ nhớ đệm developer.android.com/reference/java/lang/ref/...
Yaroslav Mytkalyk

4
@DoctororDrive tbf câu hỏi là về java, không phải dalvik! :-P
fabspro

2
@YaroslavMytkalyk, Thành thật mà nói, nếu Android muốn viết lại hành vi của một lớp, thì nó nên sử dụng không gian tên của chính nó, chứ không phải java.lang. Lạm dụng từ đồng nghĩa như vậy là không làm ai tốt cả.
Pacerier

9

Bài viết này có thể siêu hữu ích để hiểu các tài liệu tham khảo mạnh, mềm, yếu và ảo.


Để cho bạn một bản tóm tắt,

Nếu bạn chỉ có các tham chiếu yếu đến một đối tượng (không có tham chiếu mạnh), thì đối tượng đó sẽ được thu hồi bởi GC trong chu trình GC tiếp theo.

Nếu bạn chỉ có các tham chiếu mềm đến một đối tượng (không có tham chiếu mạnh), thì đối tượng đó sẽ chỉ được thu hồi bởi GC khi JVM hết bộ nhớ.


Vì vậy, bạn có thể nói rằng, các tài liệu tham khảo mạnh mẽ có sức mạnh tối thượng (không bao giờ có thể được thu thập bởi GC)

Tham chiếu mềm mạnh hơn tham chiếu yếu (vì chúng có thể thoát khỏi chu trình GC cho đến khi JVM hết bộ nhớ)

Các tham chiếu yếu thậm chí còn kém mạnh hơn các tham chiếu mềm (vì chúng không thể trích xuất bất kỳ chu trình GC nào và sẽ được thu hồi nếu đối tượng không có tham chiếu mạnh nào khác).


Nhà hàng tương tự

  • Người phục vụ - GC
  • Bạn - Đối tượng trong đống
  • Khu vực / không gian nhà hàng - Không gian heap
  • Khách hàng mới - Đối tượng mới muốn bàn trong nhà hàng

Bây giờ nếu bạn là một khách hàng mạnh (tương tự như tham chiếu mạnh), thì ngay cả khi một khách hàng mới đến nhà hàng hoặc những gì đã từng xảy ra, bạn sẽ không bao giờ rời khỏi bàn của mình (vùng nhớ trên đống). Người phục vụ không có quyền bảo bạn (hoặc thậm chí yêu cầu bạn) rời khỏi nhà hàng.

Nếu bạn là một khách hàng mềm (tương tự như tham chiếu mềm), thì nếu một khách hàng mới đến nhà hàng, người phục vụ sẽ không yêu cầu bạn rời khỏi bàn trừ khi không còn bàn trống nào khác để chứa khách hàng mới. (Nói cách khác, người phục vụ sẽ yêu cầu bạn rời khỏi bàn chỉ khi một khách hàng mới bước vào và không còn bàn nào khác cho khách hàng mới này)

Nếu bạn là một khách hàng yếu (tương tự như tham chiếu yếu), thì người phục vụ, theo ý muốn của anh ta, có thể (bất cứ lúc nào) yêu cầu bạn rời khỏi nhà hàng: P


7

Sự khác biệt thực sự duy nhất

Theo tài liệu , WeakReferences lỏng lẻo phải được xóa bởi một GC đang chạy.

Theo tài liệu , SoftReferences lỏng lẻo phải được xóa trước khi ném OOM.

Đó là sự khác biệt thực sự duy nhất. Mọi thứ khác không phải là một phần của hợp đồng. (Tôi sẽ cho rằng các tài liệu mới nhất là hợp đồng.)

SoftReferences là hữu ích. Bộ nhớ cache nhạy cảm với bộ nhớ sử dụng SoftReferences, không phải WeakReferences.


Việc sử dụng WeakReference thích hợp duy nhất là để quan sát hoạt động của GC. Bạn làm điều này bằng cách tạo một WeakReference mới có đối tượng ngay lập tức vượt ra khỏi phạm vi, sau đó cố gắng loại bỏ null weak_ref.get(). Khi đó null, bạn biết rằng trong khoảng thời gian này, GC đã chạy.

Đối với việc sử dụng WeakReference không chính xác , danh sách này là vô tận:

  • một bản hack tệ hại để thực hiện phần mềm ưu tiên 2 để bạn không phải viết một bản, nhưng nó không hoạt động như mong đợi vì bộ nhớ cache sẽ bị xóa trong mỗi lần chạy GC, ngay cả khi có bộ nhớ dự phòng. Xem https://stackoverflow.com/a/3243242/632951 để biết các phails. (Bên cạnh đó, nếu bạn cần nhiều hơn 2 cấp độ ưu tiên bộ đệm thì bạn vẫn cần một thư viện thực sự cho nó.)

  • một hack tệ hại để liên kết dữ liệu với một đối tượng của một lớp hiện có, nhưng nó tạo ra sự rò rỉ bộ nhớ (OutOfMemoryError) khi GC của bạn quyết định nghỉ sau khi các điểm yếu của bạn được tạo. Bên cạnh đó, nó còn vượt trội: Một cách tiếp cận tốt hơn là sử dụng bộ dữ liệu.

  • một hack tệ hại để liên kết dữ liệu với một đối tượng của một lớp hiện có, trong đó lớp có dây thần kinh để làm cho nó không thể phân lớp và được sử dụng trong một mã chức năng hiện có mà bạn cần gọi. Trong trường hợp như vậy, giải pháp thích hợp là chỉnh sửa lớp và biến nó thành lớp con, hoặc chỉnh sửa hàm và làm cho nó có giao diện thay vì lớp hoặc sử dụng hàm thay thế.


Điều gì về một bộ đệm trong đó loại khóa equals()chỉ là nhận dạng đối tượng? Tài liệu tham khảo mềm có vẻ như là một sự lãng phí ở đó, bởi vì một khi một đối tượng quan trọng không còn có thể tiếp cận mạnh mẽ, sẽ không ai tìm kiếm bản đồ đó nữa.
HighCommander4

Tôi không đồng ý. Sử dụng WeakReference khi bạn không muốn ảnh hưởng đến GC trong mọi trường hợp (Bạn có thể muốn lưu tham chiếu đối tượng và sau đó kiểm tra xem nó có còn tồn tại không, không có bất kỳ ưu tiên nào như vậy). Sử dụng SoftReference nếu bạn muốn tác động đến GC để thử và giữ đối tượng (tức là khi bạn muốn rằng GC sẽ giữ nó).
David Refaeli

Một ví dụ điển hình về việc sử dụng WeakReference là trong AsyncTask của Android - để giữ một ví dụ về bối cảnh. Theo cách đó, nếu bối cảnh chết (nếu hoạt động - xoay màn hình, v.v.), AsyncTask sẽ không có bất kỳ tham chiếu mạnh nào đến nó và vì vậy nó có thể được thu gom rác. Kiểm tra youtu.be/ từ
David Refaeli

3

Sáu loại trạng thái khả năng tiếp cận đối tượng trong Java:

  1. Các đối tượng có thể tiếp cận mạnh ly - GC sẽ không thu thập ( lấy lại bộ nhớ bị chiếm dụng ) loại đối tượng này. Chúng có thể truy cập thông qua một nút gốc hoặc một đối tượng có thể truy cập mạnh mẽ khác (tức là thông qua các biến cục bộ, biến lớp, biến thể hiện, v.v.)
  2. Các đối tượng mềm có thể tiếp cận - GC có thể cố gắng thu thập loại đối tượng này tùy thuộc vào sự tranh chấp bộ nhớ. Chúng có thể truy cập từ thư mục gốc thông qua một hoặc nhiều đối tượng tham chiếu mềm
  3. Các đối tượng có thể tiếp cận yếu ly - GC phải thu thập loại đối tượng này. Chúng có thể truy cập từ gốc thông qua một hoặc nhiều đối tượng tham chiếu yếu
  4. Các đối tượng có khả năng hồi sinh - GC đang trong quá trình thu thập các đối tượng này. Nhưng họ có thể quay trở lại một trong những trạng thái - Mạnh / Mềm / Yếu bằng cách thực hiện một số hoàn thiện
  5. Đối tượng có thể truy cập Phantom ly - GC đang trong quá trình thu thập các đối tượng này và đã xác định không thể phục hồi bằng bất kỳ trình hoàn thiện nào (nếu nó tự khai báo phương thức quyết toán (), thì trình hoàn thiện của nó sẽ được chạy) . Chúng có thể truy cập từ thư mục gốc thông qua một hoặc nhiều đối tượng tham chiếu ảo
  6. Đối tượng không thể truy cập - Một đối tượng không mạnh mẽ, mềm mại, yếu đuối, cũng không thể tiếp cận được với bóng ma và không thể phục hồi. Những đối tượng này đã sẵn sàng để khai hoang

Để biết thêm chi tiết: https://www.artima.com/insidejvm/ed2/gc16.html «sụp đổ


4
Không phải là một mô tả tốt về tài liệu tham khảo ảo. Ngoài ra, bạn đã liệt kê 4 loại theo thứ tự đặc biệt. "Bóng ma" là loại yếu nhất, không phải loại mạnh nhất. Thứ tự truyền thống để liệt kê những thứ này là "mạnh, mềm, yếu, ảo". Và tôi không biết bạn đã có khái niệm rằng các đối tượng ảo được sử dụng cho các cơ chế lưu trữ. AFAIK, chúng là một trạng thái tạm thời chỉ được nhìn thấy bởi GC, không phải là thứ mà một lập trình viên bình thường sẽ làm việc với.
ToolmakerSteve

@ToolmakerSteve và tất cả - Xin lỗi cho vài điều 1. giải thích sai về các tham chiếu Phantom trong phiên bản trước của câu trả lời của tôi và 2. Trì hoãn sửa lỗi. Bây giờ câu trả lời đã được cải thiện bằng cách sửa lỗi
V.Vidyasagar

1

Mọi người nên biết rằng một đối tượng được tham chiếu yếu sẽ chỉ được thu thập khi nó chỉ có (các) tham chiếu yếu. Nếu nó có quá nhiều tài liệu tham khảo mạnh, thì nó không được thu thập cho dù có bao nhiêu tài liệu tham khảo yếu.


Đây là lẽ thường ... tương tự với softref và ph Phantomref.
Pacerier

1

Để đưa ra khía cạnh sử dụng bộ nhớ trong thực tế, tôi đã thử nghiệm với các tham chiếu Mạnh, Mềm, Yếu & Phantom dưới tải nặng với các vật nặng bằng cách giữ chúng cho đến khi kết thúc chương trình. Sau đó theo dõi hành vi sử dụng heap & GC . Các số liệu này có thể thay đổi tùy theo từng trường hợp nhưng chắc chắn mang lại sự hiểu biết cao. Dưới đây là những phát hiện.

Hành vi của Heap & GC dưới tải nặng

  • Tham chiếu mạnh / cứng - Khi chương trình tiếp tục, JVM không thể thu thập đối tượng được tham chiếu mạnh được giữ lại. Cuối cùng kết thúc bằng "java.lang.OutOfMemoryError: Java heap space"
  • Tham chiếu mềm - Khi chương trình tiếp tục, việc sử dụng heap tiếp tục tăng, nhưng OLD gen GC đã xảy ra khi nó gần đạt được heap tối đa. GC bắt đầu bit sau đó trong thời gian sau khi bắt đầu chương trình.
  • Tham chiếu yếu - Khi chương trình bắt đầu, các đối tượng bắt đầu hoàn thiện & được thu thập gần như ngay lập tức. Chủ yếu là các đối tượng đã được thu thập trong bộ sưu tập rác thế hệ trẻ.
  • Tham chiếu ảo - Tương tự như tham chiếu yếu, các đối tượng tham chiếu ảo cũng bắt đầu được hoàn tất & rác được thu thập ngay lập tức. Không có GC thế hệ cũ và tất cả các đối tượng đã được thu thập trong chính bộ sưu tập rác thế hệ trẻ.

Bạn có thể nhận được nhiều hơn về đồ thị, số liệu thống kê, quan sát cho thí nghiệm này ở đây .


0

WeakReference : các đối tượng chỉ được tham chiếu yếu được thu thập ở mỗi chu kỳ GC (nhỏ hoặc đầy đủ).

SoftReference : khi các đối tượng chỉ được tham chiếu nhẹ được thu thập tùy thuộc vào:

  1. -XX: SoftRefLRUPolicyMSPerMB = N cờ (giá trị mặc định là 1000, còn gọi là 1 giây)

  2. Số lượng bộ nhớ miễn phí trong heap.

    Thí dụ:

    • heap có 10 MB dung lượng trống (sau khi có đầy đủ GC);
    • -XX: SoftRefLRUPolicyMSPerMB = 1000

    Sau đó, đối tượng chỉ được tham chiếu bởi SoftReference sẽ được thu thập nếu lần cuối cùng khi nó được truy cập lớn hơn 10 giây.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.