Search code examples
javaiopreferences

What's the difference between Preferences.flush() and Preferences.sync()?


What's the difference between Preferences.flush() and Preferences.sync()?

From the Javadoc (flush()):

Forces any changes in the contents of this preference node and its descendants to the persistent store. Once this method returns successfully, it is safe to assume that all changes made in the subtree rooted at this node prior to the method invocation have become permanent.

Implementations are free to flush changes into the persistent store at any time. They do not need to wait for this method to be called.

When a flush occurs on a newly created node, it is made persistent, as are any ancestors (and descendants) that have yet to be made persistent. Note however that any preference value changes in ancestors are not guaranteed to be made persistent.

If this method is invoked on a node that has been removed with the removeNode() method, flushSpi() is invoked on this node, but not on others.

sync():

Ensures that future reads from this preference node and its descendants reflect any changes that were committed to the persistent store (from any VM) prior to the sync invocation. As a side-effect, forces any changes in the contents of this preference node and its descendants to the persistent store, as if the flush method had been invoked on this node.

Looking at the implementations of java.util.prefs.FileSystemPreferences and java.util.prefs.WindowsPreferences, flush() merely invokes sync(), and that's it.

When dealing with other java.util.prefs implementations (in case they follow the specification):

  • What are my chances to lose the unsaved data (e. g. in case of a power outage or abnormal JVM termination) if I just flush(), but not sync()?
  • Additionally, is my understanding correct that sync() guarantees changes to become visible to other JVMs while flush() does not?

Solution

  • By default, all methods for modifying Preferences are asynchronous and guarantee eventual consistency.

    flush() is used to perform modifications synchronously i.e. by blocking the execution.

    sync() is used to commit all the pending modifications that are were supposed to happen asynchronously. In other words, sync() will block the execution and force the state to consistent before proceeding.

    To avoid losing unsaved data in case of abnormal termination, you should use flush() everywhere. I cannot comment on how this will affect the efficiency of your code.