In one of my projects, I have simultaneous write access to one file within the same JRE and you want to handle this by first writing to a temporary file and then moving this temporary file to the target using atomic move. I do not care about the write access order or such, all I need to ensure that one file can be used at any given time. I already know about Files.move and so, my problem is that I considered at least one implementation for this method, and he had some doubts as to whether the implementations really guarantee atomic moves. Take a look at the following code:
Files.move on GrepCode for OpenJDK
1342 FileSystemProvider provider = provider(source); 1343 if (provider(target) == provider) { 1344 // same provider 1345 provider.move(source, target, options); 1346 } else { 1347 // different providers 1348 CopyMoveHelper.moveToForeignTarget(source, target, options); 1349 }
The problem is that the ATOMIC_MOVE option is not considered in all cases, but the location of the source and destination paths is the only thing that matters first. This is not what I want, and as I understand the documentation:
If the move cannot be performed as an atomic file system operation, then an AtomicMoveNotSupportedException is thrown. This can occur, for example, when the target location is in another file storage and requires that the file be copied or the target location is associated with another provider of this object.
The above code clearly violates this documentation as it reverts to a copy-delete strategy without recognizing ATOMIC_MOVE at all. In my case, the exception would be perfectly normal, because the host of our service could change its settings to use only one file system that supports atomic moves, like what we expect in system requirements anyway. What I don't want to deal with are things that just fail just because the implementation uses a copy-delete strategy, which can lead to data corruption in the target file. So, from my understanding, it is simply unsafe to rely on Files.move for atomic operations, because it does not always fail if they are not supported, but implementations can return to the copy-delete strategy.
Is this behavior an implementation error and should be filed, or does the documentation allow this behavior, and I understand that this is wrong? Does it really matter if I already know that such possibly broken implementations are used there? In this case, I will need to synchronize write access ...