2009-04-23 31 views
16

Tôi tự hỏi các tham chiếu yếu hoạt động như thế nào trong nội bộ, ví dụ trong .NET hoặc Java. Hai ý tưởng chung của tôi là:Các tham chiếu yếu được triển khai như thế nào?

  1. "xâm nhập" - để thêm danh sách tham chiếu yếu vào lớp cao nhất (lớp đối tượng). Sau đó, khi một đối tượng bị phá hủy, tất cả các tham chiếu yếu có thể được lặp lại và được đặt thành null.
  2. "Không xâm nhập" - để duy trì một số chỉ mục của các đối tượng trong danh sách tham chiếu yếu. Khi một tham chiếu yếu A được tạo thành đối tượng B, sẽ có một mục nhập có thể thay đổi hoặc được tạo, khóa có thể là con trỏ đến B.
  3. "Bẩn" - để lưu trữ giá trị băm đặc biệt với từng đối tượng , sẽ bị xóa khi đối tượng bị hủy. Các tham chiếu yếu sẽ sao chép giá trị băm đó và so sánh nó với giá trị của đối tượng để kiểm tra xem đối tượng có còn sống hay không. Tuy nhiên, điều này sẽ gây ra lỗi vi phạm truy cập, khi được sử dụng trực tiếp, vì vậy sẽ cần phải có một đối tượng bổ sung với giá trị băm đó, tôi nghĩ vậy.

Một trong các giải pháp này có vẻ sạch sẽ và không hiệu quả. Có ai biết làm thế nào nó thực sự được thực hiện?

Trả lời

5

Không chắc chắn tôi đã hiểu câu hỏi của bạn, nhưng bạn có thể xem xét triển khai cho lớp WeakReference và siêu lớp của nó Tham chiếu bằng Java. Nó cũng được nhận xét và bạn có thể thấy nó có một trường được xử lý đặc biệt bởi GC và một trường khác được VM sử dụng trực tiếp.

+0

Tìm thấy: http://java.sun.com/j2se/1.5.0/source_license.html –

+0

Mới nhất tại đây: http://download.java.net/openjdk/jdk7/ –

6

Trong .NET, khi một WeakReference được tạo, GC được yêu cầu cho một mã thông báo xử lý/mờ đục đại diện cho tham chiếu. Sau đó, khi cần, WeakReference sử dụng tay cầm này để hỏi GC nếu xử lý đó vẫn hợp lệ (tức là đối tượng gốc vẫn tồn tại) - và nếu có, nó có thể lấy tham chiếu đối tượng thực tế.

Vì vậy, đây là việc xây dựng một danh sách các thẻ/xử lý chống lại các địa chỉ đối tượng (và có lẽ duy trì danh sách đó trong chống phân mảnh vv)

Tôi không chắc chắn 100% tôi hiểu ba viên đạn, vì vậy tôi ngần ngại đoán mà (nếu có) gần nhất.

+0

Sự cố có thể xảy ra là xác định xem mã thông báo có liên quan đến đối tượng gốc hay đối tượng mới xảy ra để chiếm cùng một vị trí trong bộ nhớ hay không. Tôi nghĩ rằng việc triển khai hiện tại sử dụng một cuộc gọi lại làm mất hiệu lực tham chiếu yếu khi đối tượng được hoàn thành. –

+2

Một GC nén cần phải có một giải pháp cho vấn đề đó anyway, vì nó di chuyển các đối tượng xung quanh tất cả các thời gian là tốt. –

2

Python's PEP 205 có lời giải thích hợp lý về cách tham chiếu yếu nên hoạt động trong Python và điều này cung cấp một số thông tin chi tiết về cách chúng có thể được triển khai. Vì một tham chiếu yếu là không thay đổi, bạn có thể chỉ có một đối với mỗi đối tượng, mà bạn đưa ra các tham chiếu khi cần thiết. Vì vậy, khi đối tượng bị phá hủy, chỉ có một tham chiếu yếu cần được vô hiệu.

0

Cách tiếp cận thông thường, tôi nghĩ, là để hệ thống duy trì một số loại danh sách tham chiếu yếu. Khi bộ thu gom rác thực hiện, trước khi các đối tượng chết được loại bỏ, hệ thống sẽ lặp lại thông qua danh sách các tham chiếu yếu và vô hiệu hóa bất kỳ tham chiếu nào có mục tiêu không được gắn thẻ trực tiếp. Tùy thuộc vào hệ thống, điều này có thể xảy ra trước hoặc sau khi hệ thống tạm thời phục hồi các đối tượng đủ điều kiện để hoàn thành ngay lập tức (trong trường hợp .net, có hai loại WeakReference - một trong số đó được xử lý hiệu quả trước khi hệ thống quét , có nghĩa là nó sẽ trở thành không hợp lệ khi mục tiêu của nó đủ điều kiện để hoàn thành và một trong số đó được xử lý sau). Một cách ngẫu nhiên, nếu tôi đang thiết kế một khuôn khổ dựa trên gc, tôi sẽ thêm một vài tính năng khác: (1) phương tiện khai báo một loại tham chiếu vị trí lưu trữ như giữ một tham chiếu chủ yếu được người khác quan tâm khác, và (2) Một loạt các WeakReference mà sẽ có thể chỉ ra rằng các tài liệu tham khảo duy nhất cho một đối tượng đang ở trong "quan tâm đến người khác" vị trí lưu trữ.Mặc dù WeakReference là một loại hữu ích, hành động biến một tham chiếu yếu thành tham chiếu mạnh có thể ngăn hệ thống nhận ra rằng không ai có thể quan tâm nếu mục tiêu của nó biến mất.

2

Dường như việc triển khai các tham chiếu yếu là bí mật được giữ kín trong ngành ;-). Ví dụ: tính đến thời điểm hiện tại, wikipedia article thiếu bất kỳ chi tiết triển khai nào. Và nhìn vào các câu trả lời ở trên (bao gồm cả chấp nhận): "hãy nhìn vào nguồn" hoặc "tôi nghĩ"; - \.

Trong tất cả các câu trả lời, chỉ có một tham chiếu đến PEP 205 của Python là sâu sắc. Như nó nói, đối với bất kỳ đối tượng đơn lẻ nào, có thể có tối đa một tham chiếu yếu, nếu chúng ta coi weakref là một thực thể.

Phần còn lại mô tả việc triển khai ngôn ngữ Squirrel. Vì vậy, weakref chính nó là một đối tượng, khi bạn đặt tham chiếu yếu đến một đối tượng trong một số thùng chứa, bạn thực sự đặt tham chiếu đến đối tượng weakref. Mỗi đối tượng đếm được đều có trường để lưu con trỏ tới weakref của nó, đó là NULL cho đến khi hàm weakref đến đối tượng đó thực sự được yêu cầu. Mỗi đối tượng có phương thức để yêu cầu weakref, hoặc trả về hiện tại (singleton) weakref từ trường, hoặc tạo ra nó và lưu trữ trong trường.

Tất nhiên, điểm yếu cho đối tượng gốc. Vì vậy, sau đó bạn chỉ cần đi qua tất cả các nơi có sẵn, nơi tài liệu tham khảo cho các đối tượng được xử lý và thêm xử lý minh bạch của weakrefs (tức là tự động dereference nó). ("Minh bạch" thay thế là thêm ảo "truy cập" phương pháp đó sẽ được nhận dạng cho hầu hết các đối tượng, và dereference thực tế cho weakref.)

Và như đối tượng có con trỏ đến weakref của nó, sau đó đối tượng có thể NULLify weakref trong của riêng destructor.

Triển khai này khá sạch sẽ (không có phép thuật "gọi vào GC") và có chi phí thời gian chạy O (1). Tất nhiên, nó khá tham lam của bộ nhớ - cần phải thêm trường con trỏ +1 cho mỗi đối tượng, mặc dù thường cho 90 +% đối tượng sẽ là NULL. Tất nhiên, VHLL đã có dung lượng bộ nhớ lớn trên mỗi đối tượng và có thể có các trường "thêm" nhỏ gọn khác nhau. Ví dụ, kiểu đối tượng thường là một kiểu liệt kê nhỏ, vì vậy nó có thể hợp nhất kiểu và một kiểu tham chiếu weakref vào từ máy đơn (nói, giữ các đối tượng weakref trong một đấu trường riêng biệt, và sử dụng chỉ mục đó).

Các vấn đề liên quan