Reputation: 2120
In my program I have a service object which keeps weak references to objects. I have an automated test that asserts that when all references to the object are removed, the weak reference becomes freed up. The purpose of the test is to prove that the service won't cause objects to remain in memory when there is no reason for them to be kept around.
Here is a simplified version of that test:
[Test]
public void WeakReference()
{
var o = Allocate();
var reference = new WeakReference(o.Value);
Assert.IsTrue(reference.IsAlive);
o.Value = null;
GC.Collect();
Assert.IsFalse(reference.IsAlive);
}
private MyObject Allocate()
{
return new MyObject
{
Value = new object()
};
}
private class MyObject
{
public object Value { get; set; }
}
In a .NET 4.8 NUnit test project this test passes. However, on the current branch of the project, I have the test inside of a .NET 5 project. In that project, this same test code fails because the weak reference remains "alive".
I also tried by changing the GC.Collect()
call to
GC.Collect(int.MaxValue, GCCollectionMode.Forced, blocking: true);
No dice.
Has there been a fundamental change in the way the garbage collection works in .NET 5 that makes the above code no longer work? How can I still prove that my service object is not holding onto objects in memory?
Upvotes: 2
Views: 560
Reputation: 46470
I was able to cause your test to pass under these 3 conditions:
GC.Collect()
while IsAlive
.This modified test code demonstrates the looping mentioned in #1 above and repeats the test a significant number of times. It always passes for me.
[Test, Repeat(1000)]
public void WeakReference()
{
var o = Allocate();
var reference = new WeakReference(o.Value);
Assert.IsTrue(reference.IsAlive);
o.Value = null;
for (var i = 0; i < 2 && reference.IsAlive; i++)
GC.Collect();
Assert.IsFalse(reference.IsAlive);
}
I'm not yet knowledgeable enough to say why this works exactly, but I've gathered that it has to do with the conditions that will cause an object reference to be a GC root (always reachable & not collectable by GC).
Upvotes: 2