Java之nio MappedByteBuffer的资源释放问题
使用nio的MappedByteBuffer映射内存, 在最后执行File.delete()方法的时候, 返回false, 即文件没有被删除. 原因是MappedByteBuffer在内存中也会创建文件的一个句柄, 所以必须先释放MapppedByteBuffer之后才能执行文件的删除操作.
如果使用SUN的JDK, 可以使用:
public static void clean(ByteBuffer bb) {
if (bb == null)
return;
Cleaner cleaner = ((DirectBuffer) bb).cleaner();
if (cleaner != null)
cleaner.clean();
}
如果使用SUN以外的JDK, 例如JRockit, 必须预防该API不存在, 可以借助反射机制来完成兼容代码:
public static void clean(final MappedByteBuffer mbb) {
if (mbb == null) {
return;
}
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
Method cleanerMethod = mbb.getClass().getDeclaredMethod("cleaner", new Class[0]);
if (cleanerMethod != null) {
cleanerMethod.setAccessible(true);
Object cleanerObject = cleanerMethod.invoke(mbb, new Object[0]);
Method cleanMethod = cleanerObject.getClass().getDeclaredMethod("clean", new Class[0]);
if (cleanMethod != null) {
cleanMethod.invoke(cleanerObject, new Object[0]);
}
}
} catch (Exception e) {
logger.error("关闭MappedByteBuffer句柄错误!", e);
}
return null;
}
});
}
使用AccessController目的是为了启动SecurityManager的时候也有足够的私权去释放内存句柄.