Hãy xem xét hai loại cổ phiếu này:thu rác và tham chiếu vòng tròn
public class A
{
B b;
public A(B b) { this.b = b; }
}
public class B
{
A a;
public B() { this.a = new A(this); }
}
Nếu tôi đã học được thiết kế như trên, các đối tượng của các lớp học như vậy sẽ được thu thập bởi rác Collector (GC)?
Giả sử tôi làm điều này:
void f()
{
B b = new B();
}
Trong phương pháp này, tôi tạo ra một thể hiện của B
gọi b
, và khi trở về phương pháp, b
đi ra khỏi phạm vi, và GC sẽ có thể thu thập nó , nhưng nếu thu thập nó, nó sẽ phải thu a
đầu tiên là thành viên của B
và để thu a
, trước tiên cần phải thu b
là thành viên của A
. Nó trở thành hình tròn. Vì vậy, câu hỏi của tôi là: là tham chiếu vòng tròn như vậy sẽ ngăn chặn GC thu thập các đối tượng?
- Nếu có, thì làm cách nào để tránh sự cố này? Làm cách nào để đảm bảo rằng chúng tôi không có tham chiếu vòng tròn trong thiết kế lớp học của mình? Có bất kỳ công cụ (hoặc tùy chọn trình biên dịch) giúp chúng tôi phát hiện tham chiếu vòng tròn?
- Nếu không, ở đâu và tại sao chúng tôi sử dụng
WeakReference
lớp học? Mục đích của nó là gì?
Hãy xem tại đây http://stackoverflow.com/questions/400706/circular-references-cause-memory-leak –
Ít nhất một cách hợp lý một trong các tham chiếu luôn luôn yếu: Trong ví dụ của bạn, rõ ràng 'A 'không thể phụ thuộc vào' B', bởi vì 'A' phải được tạo thành đầu tiên, là thành viên của' B', và vì vậy 'A' chỉ có thể giữ một tham chiếu yếu với' B'. Vì vậy, an toàn để tiêu diệt 'B' trước và sau đó là 'A'. Tranh luận đệ quy, mỗi chương trình máy tính phải như vậy. Không bao giờ có thể là * true *, phụ thuộc hoàn toàn đối xứng tròn. –
@KerrekSB: Tôi đồng ý với logic đó. Nhưng điều đó được nhìn từ điểm sáng tạo. Liệu GC sẽ phân tích điều này (tức là mã trong mỗi phương pháp của các lớp như vậy, sau khi tất cả chỉ sau đó nó có thể đạt được tại kết luận đó)? Ý tôi là, nếu bạn thấy các vật thể sau khi chúng được tạo ra, thì có vẻ như rất có vấn đề. – Nawaz