密封类通过限制继承和密封关键方法,从设计层面保障内存屏障不被绕过。它禁止任意子类篡改内存管理逻辑,强制所有调用走预设路径,并结合模块约束、访问控制与可信边界校验,确保屏障指令严格执行。

密封类本身不直接作用于内存屏障,但它能从设计层面切断不可控继承链,从而间接保护底层内存安全机制不被意外绕过。
明确限制继承范围,防止内存管理逻辑被篡改
公用SDK基类若涉及内存分配、引用计数、资源生命周期管理等敏感操作,开放继承可能导致子类重写关键方法(如 dispose、finalize、onMemoryWarning),跳过或弱化原有内存屏障逻辑。使用密封类可彻底禁止任意继承:
- Java 中用
sealed class BaseMemoryManager permits SafeHandler,仅允许 SDK 自身定义的、经过严格审查的子类实现 - C# 中用
sealed class MemoryGuard,确保任何调用都走预设路径,避免虚方法调用带来的运行时不确定性 - 所有许可子类必须声明为
final或sealed,杜绝进一步派生带来的内存行为漂移
配合 sealed 方法封禁关键内存操作点
即使基类无法完全密封,也可对核心内存控制方法加密封保护:
- 在基类中将
releaseNativeBuffer()、acquireDirectMemory()等方法标记为sealed override(C#)或final(Java),防止子类替换其实现 - 这些方法内部应直接调用受控的 JNI/Native 接口,并嵌入内存屏障指令(如
std::atomic_thread_fence或Unsafe.storeFence()) - 一旦方法被密封,反射绕过或字节码注入就无法改变其执行语义,保障屏障指令不被跳过
结合模块与访问控制强化可信边界
单纯语法密封不够,需叠加运行时与编译期约束:
- Java 中要求密封类及其许可子类位于同一模块,利用模块系统限制跨模块继承;Android 上还可配合
hiddenapi名单,将底层内存接口设为blocked,使第三方无法通过反射访问 - 在 SDK 初始化阶段校验调用栈,若检测到非许可包名下的继承链,主动抛出
SecurityException并终止实例化 - 对关键对象(如 DirectByteBuffer 封装器)启用
--illegal-access=deny,阻止非法反射修改其内部地址或清理器
用 non-sealed 实现可控扩展,而非放任继承
若确实需要第三方扩展能力,不应开放基类继承,而应提供受限通道:
- 定义
sealed interface MemoryObserver,只允许实现回调契约,不暴露内存操作入口 - 提供
registerCallback(Runnable cleanupHook)等受检注册方式,由 SDK 统一注入内存压力响应逻辑 - 所有外部代码只能通过不可变数据结构(如
ImmutableBytes)交互,避免持有原始指针或可变缓冲区引用


















