我真的很喜欢 WeakReference 的。但我希望有一种方法可以告诉 CLR 多少(例如,在 1 到 5 的范围内)您认为该引用有多弱。那将是辉煌的。
Java 有 SoftReference、WeakReference,我相信还有第三种类型,称为“幻像引用”。那是 3 个级别,GC 在决定该对象是否获得印章时具有不同的行为算法。
我正在考虑将.NET 的 WeakReference 子类化(幸运的是,它没有被密封)来制作一个基于过期计时器或其他东西的伪 SoftReference。
我真的很喜欢 WeakReference 的。但我希望有一种方法可以告诉 CLR 多少(例如,在 1 到 5 的范围内)您认为该引用有多弱。那将是辉煌的。
Java 有 SoftReference、WeakReference,我相信还有第三种类型,称为“幻像引用”。那是 3 个级别,GC 在决定该对象是否获得印章时具有不同的行为算法。
我正在考虑将.NET 的 WeakReference 子类化(幸运的是,它没有被密封)来制作一个基于过期计时器或其他东西的伪 SoftReference。
我认为 NET 没有软引用的根本原因是因为它可以依赖具有虚拟内存的操作系统。Java 进程必须指定它的最大操作系统内存(例如用-Xmx128M
),并且它永远不会占用比这更多的操作系统内存。而 NET 进程不断占用它需要的操作系统内存,当 RAM 用完时,操作系统会提供磁盘支持的虚拟内存。如果 NET 允许软引用,那么 NET 运行时将不知道何时释放它们,除非它深入操作系统以查看其内存是否实际在磁盘上分页(讨厌的 OS/CLR 依赖项),或者它请求运行时指定最大进程内存占用(例如,相当于-Xmx
)。我猜微软不想添加-Xmx
NET,因为他们认为操作系统应该决定每个进程获得多少 RAM(通过选择将哪些虚拟内存页面保存在 RAM 或磁盘上),而不是进程本身。
Java SoftReferences 用于创建内存敏感缓存(它们没有其他用途)。
从 .NET 4 开始,.NET 有一个System.Runtime.Caching.MemoryCache类,它可能会满足任何此类需求。
具有不同程度的弱点(优先级)的 WeakReference听起来 不错,但也可能会使 GC 的工作更难,而不是更容易。(我不知道 GC 的内部结构,但是)我会假设为 WeakReference 对象保留了某种额外的访问统计信息,以便 GC 可以有效地清理它们(例如,它可能会删除最少使用的项目第一的)。
增加的复杂性很可能不会使任何事情变得更有效,因为最有效的方法是首先摆脱不经常使用的 WeakReferences。如果你可以指定一个优先级,你会怎么做?这听起来像是过早的优化:程序员大部分时间并不真正知道并且在猜测;结果是较慢的 GC 收集周期,可能是回收了错误的对象。
但它引出了一个问题,如果你关心被回收的 WeakReference.Target 对象,它真的是 WeakReference 的好用处吗?
这就像一个缓存。您将内容塞入缓存并要求缓存在 x 分钟后使其陈旧,但大多数缓存根本不保证将其保留。它只是保证如果确实如此,它将根据请求的策略将其过期。
我对为什么不存在的猜测很简单。我想,大多数人都会把它称为一种美德,即只有一种类型的参考,而不是四种。
也许 ASP.NET 缓存类 (System.Web.Caching.Cache) 可能有助于实现您想要的?如果内存不足,它会自动删除对象:
这是一篇文章,展示了如何在 Windows 窗体应用程序中使用 Cache 类。
不要忘记您也有您的标准参考资料(您每天使用的参考资料)。这给了你一个更高的层次。
当您并不真正关心对象是否消失时,应该使用 WeakReferences,而 SoftReferences 只应该在您使用普通引用时使用,但您宁愿清除您的对象以便您耗尽内存。我不确定具体细节,但我怀疑 GC 在确定哪些对象处于活动状态时通常会通过 SoftReferences 而不是 WeakReferences 进行跟踪,但是当内存不足时也会跳过 SoftReferences。
我的猜测是 .Net 设计者觉得这种差异让大多数人感到困惑,或者 SoftReferences 增加了比他们真正想要的复杂性更多的复杂性,因此决定将它们排除在外。
附带说明一下,AFAIK PhantomReferences 主要是为虚拟机内部使用而设计的,而不是供实际客户端使用的。
也许应该有一个属性,您可以在其中指定对象 >= 在收集之前的哪个世代。所以如果你指定 1 那么它是最弱的参考。但是,如果您指定 3,那么它需要在之前的至少 3 个集合中存活下来,然后才能考虑将其用于集合本身。
我认为轨道恢复标志对此没有好处,因为到那时对象已经完成了?虽然可能是错的...
(PS:我是OP,刚刚注册。PITA,它不会从“未注册”帐户继承您的历史记录。)
不知道为什么 .NET 没有软引用。但在 Java 软引用中,恕我直言,过度使用。原因是至少在应用程序服务器中,您希望能够影响每个应用程序的 Softreferenzen 存活时间。目前这在 Java 中是不可能的。
寻找传递给构造函数的“trackResurrection”选项?
GC 类也提供了一些帮助。