JDK-8205404 : OverlappingFileLockException taking second lock using OS X with ExFAT/MS-DOS
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 8,9,10,11
  • Priority: P4
  • Status: Resolved
  • Resolution: Won't Fix
  • OS: os_x
  • CPU: x86_64
  • Submitted: 2018-06-11
  • Updated: 2018-07-03
  • Resolved: 2018-07-03
Description
ADDITIONAL SYSTEM INFORMATION :
macOS 10.13.4 using:

Java version "1.8.0_171"
Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)


A DESCRIPTION OF THE PROBLEM :
Taking a second lock on a ExFAT or MS-DOS (FAT) formatted disk using macOS 10.13.4 always results in a OverlappingFileLockException. If I use DiskUtily and format the drive to Mac OS Extended (Journaled) or Mac OS Extended (Case Sensitive, Journaled) I don't get this issue. If I plug the same drive into a Windows 10 machine I don't get the issue. It's just macOS with ExFAT or MS-DOS (FAT).

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Using DiskUtility, format an external drive to ExFAT or MS-DOS (FAT). Update the filePath variable to be the root of your drive and run the attached program.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Program to print:

filePath: /Volumes/SAMSUNG_T5/a/file.txt
Got lock: sun.nio.ch.FileLockImpl[0:9223372036854775807 exclusive valid]
filePath: /Volumes/SAMSUNG_T5/b/file.txt
Got lock: sun.nio.ch.FileLockImpl[0:9223372036854775807 exclusive valid]

ACTUAL -
Unable to take the second lock:

filePath: /Volumes/SAMSUNG_T5/a/file.txt
Got lock: sun.nio.ch.FileLockImpl[0:9223372036854775807 exclusive valid]
filePath: /Volumes/SAMSUNG_T5/b/file.txt
Exception in thread "main" java.nio.channels.OverlappingFileLockException
	at sun.nio.ch.SharedFileLockTable.checkList(FileLockTable.java:255)
	at sun.nio.ch.SharedFileLockTable.add(FileLockTable.java:152)
	at sun.nio.ch.FileChannelImpl.tryLock(FileChannelImpl.java:1108)
	at java.nio.channels.FileChannel.tryLock(FileChannel.java:1155)
	at LockDemo.takeLock(LockDemo.java:35)
	at LockDemo.main(LockDemo.java:25)


---------- BEGIN SOURCE ----------
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Files;
import java.nio.file.Paths;

public class LockDemo
{

    public static void main(
        String[] args) throws IOException
    {
        final String filePath = "/Volumes/SAMSUNG_T5";
        final String a = filePath + File.separator + "a";
        final String b = filePath + File.separator + "b";
        
        Files.createDirectories(Paths.get(a));
        Files.createDirectories(Paths.get(b));

        takeLock(a);
        takeLock(b);
    }
    
    private static void takeLock(
        final String pathname) throws IOException
    {
        final String filePath = pathname + File.separator + "file.txt";
        System.out.println("filePath: " + filePath);
        final FileOutputStream os = new FileOutputStream(new File(filePath), true);
        final FileChannel channel = os.getChannel();
        FileLock lock = channel.tryLock();
        System.out.println("Got lock: " + lock);
    }
    
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
None.

FREQUENCY : always



Comments
FAT is legacy and there have been no other complaints about this problem in 16 years. Resolving this as not to be fixed for now but if it turns out to be a more commonly observed problem it can be investigated again.
03-07-2018

If the two files (on the same device) have the same inode number then it's not possible to distinguish them. This sounds like an issue with the underlying file system support rather than a JDK issue.
03-07-2018

"In the FAT file system, the file ID is generated from the first cluster of the containing directory and the byte offset within the directory of the entry for the file. Some defragmentation products change this byte offset. [...] Thus, a FAT file ID can change over time. Renaming a file in the FAT file system can also change the file ID, but only if the new file name is longer than the old one." Windows BY_HANDLE_FILE_INFORMATION structure https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788(v=vs.85).aspx
21-06-2018

In fact this is exactly the case here as found via testing: all files on the ExFAT volume have the same device and inode numbers as returned by fstat(2). Hence the FileKey for all is the same hence the erroneous OverlappingFileLockException.
20-06-2018

Formatted a USB2.0 flash drive to MS-DOS (FAT) on Mac-OS(17.4.0 Darwin) and ran the test case provided in the bug report after modifying the path name. JDK 8u171 - Fail JDK 10.0.1 - Fail JDK 11-ea+13 - Fail Output : dcsuser$ /Users/dcsuser/Downloads/JDK/11+13/jdk-11.jdk/Contents/Home/bin/java LockDemo filePath:/Volumes/UNTITLED/a/file.txt Got lock: sun.nio.ch.FileLockImpl[0:9223372036854775807 exclusive valid] filePath:/Volumes/UNTITLED/b/file.txt Exception in thread "main" java.nio.channels.OverlappingFileLockException at java.base/sun.nio.ch.FileLockTable.checkList(FileLockTable.java:229) at java.base/sun.nio.ch.FileLockTable.add(FileLockTable.java:123) at java.base/sun.nio.ch.FileChannelImpl.tryLock(FileChannelImpl.java:1161) at java.base/java.nio.channels.FileChannel.tryLock(FileChannel.java:1160) at LockDemo.takeLock(LockDemo.java:26) at LockDemo.main(LockDemo.java:19)
20-06-2018