You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 11中强制释放MappedByteBuffer内存映射:解决sun.misc.Cleaner找不到问题

解决Java 11中sun.misc.Cleaner找不到的MappedByteBuffer内存释放问题

问题根源

Java 9起sun.misc.Cleaner被标记为废弃,Java 11中完全从JDK中移除,导致你通过反射加载该类时抛出ClassNotFoundException。而java.lang.ref.Cleaner是Java 9引入的公开标准API,属于java.base核心模块,默认即可使用,无需额外JVM参数启用内部模块,是官方推荐的替代方案。

修改后的实现代码

替换原来的反射逻辑,改为获取java.lang.ref.Cleaner实例并调用其clean()方法:

/**
 * Clean a {@code MappedByteBuffer}. Method to call to delete memory of the file and free the resources
 * @param pByteBuffer Buffer to clean
 */
private void freeByteBuffer(ByteBuffer pByteBuffer) {
    try {
        // 获取MappedByteBuffer的私有cleaner方法,返回java.lang.ref.Cleaner实例
        Method cleanerMethod = pByteBuffer.getClass().getMethod("cleaner");
        cleanerMethod.setAccessible(true);
        Cleaner cleaner = (Cleaner) cleanerMethod.invoke(pByteBuffer);
        
        if (cleaner != null) {
            cleaner.clean();
        }
    } catch (Exception ex) {
        logger.error(KernelError.FREE_MEM, idefixComponentName, ex);
    }
}

关键注意事项

  • 无需额外JVM参数(Java 11-15):java.lang.ref.Cleaner属于java.base模块的公开API,默认对所有应用可见,不需要添加--add-modules或其他模块相关参数。
  • Java 16+的特殊处理:从Java 16开始,JDK加强了模块访问控制,反射访问模块内私有成员会被限制。如果你的应用需要运行在Java 16及以上版本,需要添加JVM启动参数:
    --add-opens java.base/java.nio=ALL-UNNAMED
    
    这条参数允许你的应用(未命名模块)访问java.nio模块中的私有成员,保证反射调用cleaner()方法正常工作。

额外说明

虽然反射调用私有方法不是最理想的实践,但这是目前跨Java 8到Java 17+版本主动释放MappedByteBuffer资源的通用方案。如果你的应用不再需要兼容Java 8,也可以考虑使用FileChannel的force()方法配合GC自动回收,但主动调用Cleaner的方式能更及时地释放内存资源。

内容的提问来源于stack exchange,提问作者Etienne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 04:20:59