FULL PRODUCT VERSION :
java version " 1.7.0_09 "
Java (TM) SE Runtime Environment (build 1.7.0_09-b05)
Java HotSpot (TM) 64-Bit Server VM (build 23.5-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
MappedByteBuffer does not provide a unmap method to unmap a memory-mapped file. Our application uses memory-mapped IO to read data from memory-mapped archive files. If new data is added to one of the archive files, the old file is deleted and a new file is created. On Windows it is not possible to delete memory-mapped files. As a workaround we renamed mapped files we want to delete and deleted them after the GC has unmapped the file.
With Java Plattform Standard Edition 6.0 it was possible to rename memory-mapped files on Windows using File.renameTo(File dst). Unfortunately that is no longer possible with Java 7.
With Java 7 our only option now seems to be to use
sun.misc.Cleaner cleaner = ((DirectBuffer) buffer).cleaner();
cleaner.clean();
and then delete the file. Please either make it possible to rename memory-mapped files on Windows again or preferably add a unmap method to MappedByteBuffer.
REGRESSION. Last worked in version 6u31
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Open a file, get the filechannel, then create a mapped byte buffer. Try to rename the file using file.renameTo(dst) or Files.move(src, dst, StandardCopyOption.REPLACE_EXISTING).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
file.renameTo(dst) or Files.move(src, dst, StandardCopyOption.REPLACE_EXISTING) should rename memory-mapped files on Windows.
ACTUAL -
Memory-Mapped files cannot be renamed on Windows. Files.move(src, dst, StandardCopyOption.REPLACE_EXISTING) will throw an exception:
java.nio.file.FileSystemException: c:\Temp\test.bin -> c:\Temp\test2.bin: The process cannot access the file because it is being used by another process.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.nio.file.FileSystemException: c:\Temp\test.bin -> c:\Temp\test2.bin: The process cannot access the file because it is being used by another process.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package mappedbytebuffertest;
import sun.nio.ch.DirectBuffer;
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
public class Main {
public static void main(String[] args) throws Exception {
File file = new File( " c:\\Temp\\test.bin " );
// create file and add some data to it if it does not already exist
if (!file.exists()) {
FileOutputStream fout = new FileOutputStream(file);
DataOutputStream dout = new DataOutputStream(fout);
for(int i = 0; i < 1024; i++) dout.write(i);
dout.close();
fout.close();
}
// now map the file
FileInputStream is = new FileInputStream(file);
MappedByteBuffer buffer = is.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, is.getChannel().size());
is.close();
// now try to rename the file
File dst = new File( " c:\\Temp\\test2.bin " );
if (file.renameTo(dst)) System.out.println( " Renamed file to " + dst); else System.out.println( " Could not rename file to " + dst);
// try the new JDK 7 API
Path path = file.toPath();
Path dstPath = dst.toPath();
try {
Files.move(path, dstPath, StandardCopyOption.REPLACE_EXISTING);
System.out.println( " Renamed file to " + dstPath);
} catch (IOException ex) {
System.out.println( " Could not rename file to " + dstPath + " reason: " + ex);
}
// now unmap the file
sun.misc.Cleaner cleaner = ((DirectBuffer) buffer).cleaner();
cleaner.clean();
// try the new JDK 7 API
try {
Files.move(path, dstPath, StandardCopyOption.REPLACE_EXISTING);
System.out.println( " Renamed file to " + dstPath);
} catch (IOException ex) {
System.out.println( " Could not rename file to " + dstPath + " reason: " + ex);
}
}
}
Running this programm will produce the following output:
Could not rename file to c:\Temp\test2.bin
Could not rename file to c:\Temp\test2.bin reason: java.nio.file.FileSystemException: c:\Temp\test.bin -> c:\Temp\test2.bin: The process cannot access the file because it is being used by another process.
Renamed file to c:\Temp\test2.bin
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Unmap the file before renaming it, using:
sun.misc.Cleaner cleaner = ((DirectBuffer) buffer).cleaner();
cleaner.clean();