Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File Last Modified Not Updating when Java Writes to Windows Server 2016

I have a Java 10 application on Windows Server 2016 which is continually writing to a file using java.util.logging. In Windows File Explorer, the "Last modified" and "Size" columns do not update. Pressing [F5] does not update the details. DOS DIR gives the same incorrect answer. Right Click > Properties > Details gives an even different (and older) answer.

Only running DOS TYPE or opening/closing (without save) in Notepad on the file, seems to cause File Explorer and DOS DIR to update.

I assume the Java code is correct with respect to flush() as the same classes on Java 8 on Windows Server 2008 causes File Explorer to update. Also when running TYPE and Notepad I also see the timestamped records matching the system clock, but well after "Last Modified".

So I assume that there is something up with Windows Server 2016. Any ideas what to check?

like image 347
lafual Avatar asked Jul 31 '18 10:07

lafual


Video Answer


1 Answers

So I assume that there is something up with Windows Server 2016. Any ideas what to check?

By default Windows is setup to work this way. From File timestamp not updating on 2008 but does on 2003:

On 2003, opening the log file folder in explorer, you can see the timestamp and files size change before your eyes each time the log is updated.

On 2008, most of the time, there is no change unless you interact in some other way...

[snip]

Yes, some of these attributes have been disabled in 2008. If you want for example want to see/use “Last Accessed” time you need to enable the tracking of this attribute.

You can enable this by setting HKLM\System\CurrentControlSet\Control\FileSystem\NtfsDisableLastAccessUpdate to 0 (this value is REG_DWORD).

Please beware that his could impact disk IO performance on busy file servers !

So the behavior was change to improve performance.

From the Performance Tuning Web Servers:

The system-global switch NtfsDisableLastAccessUpdate (REG_DWORD) 1 is located under HKLM\System\CurrentControlSet\Control\FileSystem and is set by default to 1. This switch reduces disk I/O load and latencies by disabling date and time stamp updating for the last file or directory access. Clean installations of Windows Server 2016, Windows Server 2012 R2, Windows Server 2012, Windows Server 2008 R2, and Windows Server 2008 enable this setting by default, and you do not need to adjust it. Earlier versions of Windows did not set this key. If your server is running an earlier version of Windows, or it was upgraded to Windows Server 2016, Windows Server 2012 R2, Windows Server 2012, Windows Server 2008 R2, or Windows Server 2008, you should enable this setting.

It appears that this setting can still be used in Windows Server 2016.

I assume the Java code is correct with respect to flush() as the same classes on Java 8 on Windows Server 2008 causes File Explorer to update. Also when running TYPE and Notepad I also see the timestamped records matching the system clock, but well after "Last Modified".

Flush is not the same as sync. The FileHandler just performs a flush after each record is published. Windows is not setup to force a writing of the metadata to the file system. From File “Date modified” property are not updating while modifying a file without closing it.:

On 2008, "Last Modified" field on log files is not updated unless another program attempts to open the file or the utility is stopped, even if F5 is pressed to refresh the view.

Explorer gets is information from NTFS, by using a cmd prompt and "dir" we found that the NTFS metadata for the files is not updated until the handle to a file is closed.

Refreshing the information of a FOLDER is just going to go to the (memory resident) metadata cached by NTFS, but querying the file explicitly will force disk I/O to get the properties - this was a design change introduced in Vista to reduce unnecessary disk I/O to improve performance

There are some exceptions to this rule:

  • in some, but not all, cases a simple "dir filename" is enough to refresh the metadata
  • "special" folders may be treated differently, such as user profiles where we do not expect a large number of files and want to be able to rely on the file data presented
  • kernel filter drivers may change the behaviour as by design they "add, remove or change functionality of other drivers"

As the workaround is for any process to open and close a handle to the log files, a tool was written to do exactly that, plus get the file information, using the following APIs:

  • CreateFile
  • GetFileInformationByHandle
  • CloseHandle

You might be able to attempt to open a FileInputStream using the file name that the FileHandler created.

Only running DOS TYPE or opening/closing (without save) in Notepad on the file, seems to cause File Explorer and DOS DIR to update.

The only universal method I've found for updating the metadata from an outside process is to select a file using the file explorer interactively:

explorer /select, c:\test\file.txt

Most likely this is very similar to what is happening in notepad.

I like your use of TYPE command. You can use that with the nul to ignore the output.

type filename.log > NUL

It is possible that running dir with metadata switches might force the update of metadata:

dir /A /R /Q filename.log > nul
like image 73
jmehrens Avatar answered Nov 14 '22 23:11

jmehrens