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的时候也有足够的私权去释放内存句柄.

posted @ 2016-09-07 14:18  HEZOF  阅读(613)  评论(0编辑  收藏  举报