@Override
  public synchronized FileLock tryLock(long position, long size, boolean shared)
      throws IOException {
    if (shared) {
      if (!data.lockShared()) {
        return null;
      }
    } else {
      if (!data.lockExclusive()) {
        return null;
      }
    }

    // cast to FileChannel to avoid JDK 1.7 ambiguity
    FileLock lock =
        new FileLock((FileChannel) null, position, size, shared) {

          @Override
          public boolean isValid() {
            return true;
          }

          @Override
          public void release() throws IOException {
            data.unlock();
          }
        };
    return lock;
  }
 @Override
 public void moveTo(FilePath newName) {
   synchronized (MEMORY_FILES) {
     FileNioMemData f = getMemoryFile();
     f.setName(newName.name);
     MEMORY_FILES.remove(name);
     MEMORY_FILES.put(newName.name, f);
   }
 }
 @Override
 public FileChannel truncate(long newLength) throws IOException {
   if (newLength < size()) {
     data.touch(readOnly);
     pos = Math.min(pos, newLength);
     data.truncate(newLength);
   }
   return this;
 }
 @Override
 public int write(ByteBuffer src) throws IOException {
   int len = src.remaining();
   if (len == 0) {
     return 0;
   }
   data.touch(readOnly);
   pos = data.readWrite(pos, src, 0 /*because we start writing from src.position()*/, len, true);
   src.position(src.position() + len);
   return len;
 }
 @Override
 public int read(ByteBuffer dst) throws IOException {
   int len = dst.remaining();
   if (len == 0) {
     return 0;
   }
   long newPos = data.readWrite(pos, dst, dst.position(), len, false);
   len = (int) (newPos - pos);
   if (len <= 0) {
     return -1;
   }
   dst.position(dst.position() + len);
   pos = newPos;
   return len;
 }
 @Override
 public String toString() {
   return data.getName();
 }
 @Override
 public long size() {
   return data.length();
 }