JDK-8206888 : When appending a byte to a file, 2GB of data are written
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 8,9,10,11
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_8
  • CPU: x86_64
  • Submitted: 2018-06-29
  • Updated: 2018-09-11
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Description
ADDITIONAL SYSTEM INFORMATION :
Windows Server 2008 R2 terminal server
Windows 7 Professional SP 1 as TS client

A DESCRIPTION OF THE PROBLEM :
Environment: Terminal Server (Windows RDP) connection, client disk mapped to a drive on a remote server.

When appending data, even a single byte, to a file which resides on the mapped drive, the JVM writes 2GB of data.

This issue can be reproduced:
- either via java.io.FileOutputStream and java.nio.file.Files.write
- both writing a new and an already existing file
- both with 32bit and 64bit JVM

This problem appeared recently, probably due some windows update.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Connect to a remote Windows 8 via RDP.
Map a local drive to a server disk, for example by issuing the command:  net use X: \\TSCLIENT\C
Run a java program which writes a single byte to a file located in the mapped drive, opening it in append mode.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Only the actually written data is appended to the file, creating it if it doesn't exists.
ACTUAL -
2GB of content are skipped before the actual write, resulting in 2GB + 1byte sized file.

---------- BEGIN SOURCE ----------
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class Append {
	public static void main(String[] args) throws Exception {
		Files.write(Paths.get(args[0]), new byte[] { 'a' }, StandardOpenOption.APPEND, StandardOpenOption.CREATE);
                // the following code also reproduces the bug
//		FileOutputStream os = new FileOutputStream(new File(args[0]), true);
//		os.write(new byte[] { 'a' });
//		os.flush();
//		os.close();
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
No known workarounds

FREQUENCY : always



Comments
Submitter's response: >>Can you let us know what happens if the C program provided by you were modified to pass NULL instead of &ov as the last parameter of WriteFile() and also the result of following changes If I pass NULL instead of &ov the program behaves correctly, except for the fact that it's overwriting the file instead of appending data to the end. For the following tests I reset the WriteFile call passing &ov again. >>1) replace GENERIC_READ | GENERIC_WRITE with FILE_APPEND_DATA, or Weird: it doesn't write the data to the file but it is created if it does not exists, resulting in a 0 byte file. >>2) insert SetFilePointer(hFile, 0, NULL, FILE_END) just before WriteFile() without change 1, or Writes 2GB of data. This line seems to have no effect. >>3) make both changes 1 and 2. Same as (1). All the executables produced by these builds behave correctly on a local filesystem, appending one byte of data and creating the file if it does not exists. By the way, I was able to reproduce the bug with just a Windows 7 Professional by downaloading Win2008 Evalutation ISO and running it with VirtualBox: https://www.microsoft.com/en-us/download/details.aspx?id=11093
23-07-2018

Resolving as Incomplete for now pending receipt of additional information requested of the submitter.
18-07-2018

Perhaps the submitter could be asked to test what happens if the above C program were modified to pass NULL instead of &ov as the last parameter of WriteFile() and also to 1) replace GENERIC_READ | GENERIC_WRITE with FILE_APPEND_DATA, or 2) insert SetFilePointer(hFile, 0, NULL, FILE_END) just before WriteFile() without change 1, or 3) make both changes 1 and 2. Reference: https://docs.microsoft.com/en-us/windows/desktop/fileio/appending-one-file-to-another-file
12-07-2018

If the C program can reproduce the issue it sounds like a Microsoft bug, not a Java bug.
12-07-2018

From submitter: I can confirm that in order to reproduce the issue a windows server 2008 is needed and the writing must be targeted on a client disk shared on the remote computer. I checked openjdk sources and tracked down the problem to an improper behavior of windows WriteFile API, which in such environment disattends what's written in the documentation: (extracted from https://docs.microsoft.com/en-gb/windows/desktop/api/fileapi/nf-fileapi-writefile) To write to the end of file, specify both the Offset and OffsetHigh members of the OVERLAPPED structure as 0xFFFFFFFF. This is functionally equivalent to previously calling the CreateFile function to open hFile using FILE_APPEND_DATA access. The following C program can be used to reproduce the issue: --------------------------------------------------------------- #include <windows.h> #include <stdio.h> int main(int argc, char *argv[]) { if (argc < 2) { printf("Not enough args\n"); return 1; } HANDLE hFile = CreateFile(argv[1], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); DWORD nw; OVERLAPPED ov; ov.Offset = (DWORD)0xFFFFFFFF; ov.OffsetHigh = (DWORD)0xFFFFFFFF; ov.hEvent = NULL; WriteFile(hFile, "a", 1, &nw, &ov); CloseHandle(hFile); return 1; }
11-07-2018

There may be something in the environment too, the bug report mentions a mapped drive but does not say if this is another Windows machine, a Linux server with SAMBA, ... I think more info is needed to duplicate and see if it's a JDK issue or not.
09-07-2018

To submitter: Is the issue reproducible only on Windows Server 2008 ? I tried to reproduce the issue using two Windows 7 machines, but couldn���t reproduce the issue. Can you also confirm if the issue is reproducible even with the latest JDK versions like JDK 10.0.1 and JDK 11-ea ?
09-07-2018