【发布时间】:2011-12-05 08:40:59
【问题描述】:
我目前正在研究世代垃圾收集器。这意味着只有最近的对象被遍历,幸存的对象(=从已知的根可以到达)被提升到老一代。当对象指向相同或老一代的其他对象时,这可以正常工作。但是,当较旧的对象指向较新的对象时,并且由于仅遍历较新的对象,指向的对象将被错误地收集。为避免这种情况,此类对象在每个 GC 阶段都会被显式标记和遍历。
显然这样的“父”对象是可变的,因为通过构造不可变的对象总是指向现有的对象。所以要成为“父”,一个对象必须在提升后进行修改,使其指向一个较新的对象。
要知道老一代的哪些对象指向年轻一代,我正在寻找一种透明地监控内存变化的方法。为此,我使用内存保护和信号/异常处理。内存页面设置为只读,这会导致在写入时引发信号/异常,在这种情况下,我将内存保护设置回读写并将地址记录在某处以进行进一步处理,并返回负责的代码异常恢复正常。这样,当 GC 触发时,我就知道去哪里寻找潜在的父母进行遍历。
在 Linux 上,我结合使用 mprotect/SIGSEGV 信号处理。在 Windows 上,我打算使用 VirtualProtect,但没有发现 SIGSEGV 处理的等效项。所以我的问题:
您将如何在 Windows 上执行此操作?异常处理 API 似乎相当混乱。
有没有更好的方法来知道哪些内存区域被修改了,这样我就不必做所有这些记账了?
我的代码是用纯 C 编写的。目前我需要调用者代码来显式标记修改的对象,但这很繁琐且容易出错,所以我正在寻找一种透明的方式来完成它。
提前致谢,弗雷德
【问题讨论】:
-
结构化异常处理。
-
我没有足够的专家来判断它是否真的相关,但你可能想看看这篇关于 pitfalls 的一种尝试和捕获内存探测的博客文章。跨度>
-
SEH 不幸需要 1. 编译器支持和 2. 将 try 块包装在客户端代码周围,因此它不适合我的目的。然而,VEH 可以工作。
-
FWIW,高性能虚拟机通常会在生成机器代码(例如在 JIT 中)时挂钩指针写入,并发出代码,该代码也会将脏页提示写入特殊数组,因为使用虚拟机完成这项工作是很慢。
标签: c linux winapi garbage-collection memory-mapping