## Castrol Honda 超级摩托车:复古游戏调试故事 最近发现一款1998年的PC摩托车竞速游戏《Castrol Honda 超级摩托车世界冠军》,在现代Windows 7上运行却出乎意料地困难。虽然它与较旧的系统如Windows 98和XP兼容,但在较新的操作系统上会崩溃或冻结。根本原因?在于游戏通过DirectInput枚举输入设备时存在缓冲区溢出。 这款游戏使用DirectX 5构建,试图列出所有连接的设备,包括现代主板的LED控制器,超过了其内部数组有限的8个设备容量。这会覆盖关键数据,导致崩溃。 一个巧妙的修复方案被实现为一个2KB的DLL shim,拦截DirectInputCreateA函数。该shim过滤设备枚举,只包含操纵杆/游戏控制器,或者在找到八个设备后停止枚举,从而防止溢出。作者细致地优化了shim以实现最小的尺寸,利用了`/NODEFAULTLIB`和`#[no_std]`等技术,甚至解决了链接器的一些问题,以最大限度地兼容旧版本的Windows。补丁已在GitHub上提供,为这款经典游戏注入了新的生命。
## 瓦尔哈拉计划与序列化问题
Cay Horstmann 的瓦尔哈拉计划旨在将 Java 对象表示为原始值以提高性能——本质上是将“引用”转换为直接数据。一个关键的演示涉及扁平化 `LocalDate` 对象数组,显著加快了处理速度。然而,在从 Git 仓库构建时,使用瓦尔哈拉早期访问版本获得的初步成功并不容易实现。
罪魁祸首?序列化。虽然瓦尔哈拉允许 `LocalDate` 可能适合 8 个字节(包括空值指示符),但标准的 `LocalDate` 实现使用 `writeReplace` 以不同的方式序列化数据,这与其内部表示不同,以实现向后兼容性。Java 25 构建中的一个临时优化——将 `LocalDate` 的月份和天字段更改为字节——实现了扁平化,但由于在序列化 `LocalDate.class` 对象本身时出现问题而被撤销。
核心问题在于 Java 的序列化协议,它在反序列化期间比较字段定义。即使序列化数据本身仍然兼容,当前类定义与序列化类定义之间的字段类型不匹配也会导致序列化类对象时失败。一个建议的解决方案是显式声明 `LocalDate` 没有可序列化字段,从而允许继续扁平化。这凸显了序列化的复杂性以及为长期兼容性设计稳定线路格式的重要性。