是否可以使用反射修改 ReadOnlyCollection
我正在处理一个 SDK,只要主连接对象在范围内,它就会保留对其创建的每个对象的引用。定期创建新的连接对象会导致其他资源问题,这不是一个选项。
为了完成我需要做的事情,我必须迭代数千个这样的对象(几乎 100,000 个),虽然我当然不会保留对这些对象的引用,但我正在使用的 SDK 中的对象模型会保留这些引用。这会消耗内存,并且非常接近导致 OutOfMemoryExceptions。
这些对象存储在嵌套的 ReadOnlyCollections 中,所以我现在尝试的是在使用完这些集合后使用反射将其中一些集合设置为 null,以便垃圾收集器可以收集已使用的内存。
foreach (Build build in builds)
{
BinaryFileCollection numBinaries = build.GetBinaries();
foreach (BinaryFile binary in numBinaries)
{
this.CoveredBlocks += binary.HitBlockCount;
this.TotalBlocks += binary.BlockCount;
this.CoveredArcs += binary.HitArcCount;
this.TotalArcs += binary.ArcCount;
if (binary.HitBlockCount > 0)
{
this.CoveredSourceFiles++;
}
this.TotalSourceFiles++;
foreach (Class coverageClass in binary.GetClasses())
{
if (coverageClass.HitBlockCount > 0)
{
this.CoveredClasses++;
}
this.TotalClasses++;
foreach (Function function in coverageClass.GetFunctions())
{
if (function.HitBlockCount > 0)
{
this.CoveredFunctions++;
}
this.TotalFunctions++;
}
}
FieldInfo fi = typeof(BinaryFile).GetField("classes", BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(binary, null);
}
当我检查 numBinaries[0] 中类成员的值时,它返回 null,这似乎完成了任务,但是当我运行此代码时,内存消耗不断增加,就像我不运行时一样快完全将类设置为空。
我试图弄清楚这种方法是否存在本质上的缺陷,或者是否有另一个对象保留对我所缺少的类 ReadOnlyCollection 的引用。
I'm dealing with an SDK that keeps references to every object it creates, as long as the main connection object is in scope. Creating a new connection object periodically results in other resource issues, and is not an option.
To do what I need to do, I must iterate through thousands of these objects (almost 100,000), and while I certainly don't keep references to these objects, the object model in the SDK I'm using does. This chews through memory and is dangerously close to causing OutOfMemoryExceptions.
These objects are stored in nested ReadOnlyCollections, so what I'm trying now, is to use reflection to set some of these collections to null when I'm done with them, so the garbage collector can harvest the used memory.
foreach (Build build in builds)
{
BinaryFileCollection numBinaries = build.GetBinaries();
foreach (BinaryFile binary in numBinaries)
{
this.CoveredBlocks += binary.HitBlockCount;
this.TotalBlocks += binary.BlockCount;
this.CoveredArcs += binary.HitArcCount;
this.TotalArcs += binary.ArcCount;
if (binary.HitBlockCount > 0)
{
this.CoveredSourceFiles++;
}
this.TotalSourceFiles++;
foreach (Class coverageClass in binary.GetClasses())
{
if (coverageClass.HitBlockCount > 0)
{
this.CoveredClasses++;
}
this.TotalClasses++;
foreach (Function function in coverageClass.GetFunctions())
{
if (function.HitBlockCount > 0)
{
this.CoveredFunctions++;
}
this.TotalFunctions++;
}
}
FieldInfo fi = typeof(BinaryFile).GetField("classes", BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(binary, null);
}
When I check the values of the classes member in numBinaries[0], it returns null, which seems like mission accomplished, but when I run this code the memory consumption just keeps going up and up, just as fast as when I don't set classes to null at all.
What I'm trying to figure out is whether there's something intrinsically flawed in this approach, or if there's another object keeping references to the classes ReadOnlyCollection that I'm missing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我能想到几个替代方案...
!gcroot
是一个起点。但尽管如此,如果这确实是一个问题,我会花更多时间与第 3 方 API 提供商合作 - 在某些时候他们可能会发布您想要的更新来打破这个问题 - 然后您将回到第一个方向,或者更糟糕的是,您可能会在产品中引入细微的错误。
I can think of a few alternatives...
!gcroot
is a place to start.But despite all of that, if this really is a problem, I would spend more time with the 3rd party API provider - at some point they may release an update you want that breaks this - and you'll be back to square one, or worse you can introduce subtle bugs in the product.