0

I'm using File.createTempFile to create regular files I want to keep, the reason I use this method is because it guarantees a unique file name. However I'm seeing a strange thing with files created by this method: After I flush and closed the output stream on this file, I crash the machine running JVM deliberately, I assumed since the stream is flushed and closed, the file should contain valid data. However, sometimes the file gets filled with 0x0 instead (Note I'm testing this on a VMWare box running WinXP and latest Sun JVM 1.6).

Is the problem caused by the temp file or is this some kind of general problem which applies to all Java file io? What should I do to ensure the data gets flushed to harddrive?

Thanks

su27k
  • 15
  • 1
  • 5
  • 1
    First show us your I/O code, then we can blame it on Java. – Alexander Pogrebnyak Aug 26 '10 at 17:41
  • I'm using old style io: File file = File.createTempFile(FILE_PREFIX, FILE_SUFFIX, myDirectory); FileOutputStream fout = new FileOutputStream(file); ObjectOutputStream out = new ObjectOutputStream(fout); out.writeObject(obj); out.flush(); out.close(); – su27k Aug 27 '10 at 01:25

2 Answers2

0

Most modern filesystem access is subject to this sort of problem - see about filesystem journaling for a quick introduction to the problem.

The short of it is - if your system crashes, recently updated files may revert to previous data. If you recently created the file, it may be zero-filled.

On UNIX you prevent this using fsync and/or fdatasync. I'm not a Windows guy but this might be a starting point: cross platform fsync(). I'm not sure how to do it from Java.

Steven Schlansker
  • 37,580
  • 14
  • 81
  • 100
  • His claim is that he closed file properly before crashing VM. I suspect there is something wrong with the I/O code that writes to this file. – Alexander Pogrebnyak Aug 26 '10 at 17:44
  • 1
    A few other SO questions indicate that closing is not sufficient. Here's one... http://stackoverflow.com/questions/730521/really-force-file-sync-flush-in-java – Steven Schlansker Aug 26 '10 at 18:13
0

In addition to flush(), try calling output.getFileDescriptor().sync() on your FileOutputStream.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • This seems to be the ideal method, unfortunately, it doesn't work. If I wait a while longer before the crash, I can see the log (the log file suffers the same problem as the data file, so if I crash immediately the log is lost too, no way to know what happened), and it shows sync method fails with SyncFailedException every time I called it (tried 5 times in a for loop). So I suspect the underlying OS doesn't support this. (Note: when I can see the log, even if sync failed, the data still get written successfully, but it still fails if I crash the machine very soon after stream closure (1-2s). – su27k Aug 27 '10 at 02:15
  • Sorry, I made a mistake in my test code, sync() is the correct method to use, thanks! – su27k Aug 27 '10 at 11:13