Accessing Preferences from ShutdownHook?

P

Peter Duniho

I am trying to save some data during user shutdown. To this end, I've
added a ShutdownHook to run when the application shuts down
(Runtime.addShutdownHook()), and in the run() method for the Thread
instance added, I use the Preferences class to save data.

What I found is that unless I call Preferences.flush(), the data wasn't
actually saved. On the one hand, this doesn't seem like an unreasonable
requirement. On the other hand, the documentation _explicitly_ states:

Normal termination of the Java Virtual Machine
will not result in the loss of pending updates
-- an explicit flush invocation is not required
upon termination to ensure that pending updates
are made persistent.

Which to me seems to mean that as long as I don't care when the data is
saved, that it _will_ be saved.

Since it's definitely not being saved, this makes me wonder if it's kosher
to save data to the user preferences at all. On the one hand, I did get
it to work by explicitly flushing the preferences node, but on the other
hand the fact that this was necessary at all suggests that maybe I
shouldn't be trying to access the preferences from my shutdown hook in the
first place.

The documentation for Runtime.addShutdownHook() says, with respect to the
shutdown hook itself:

... They should also not rely blindly upon services
that may have registered their own shutdown hooks
and therefore may themselves in the process of
shutting down.

Since the Preferences class is documented as having at least some degree
of asynchronous behavior, it seems possibly (likely?) that it has its own
shutdown hooks, and thus is relevant to that quote.

At the very least, that would explain why in spite of the Preferences
class saying that you don't need to call flush(), that you actually do in
this case. After all, the Preferences class might already believe it's
done writing all pending preferences out by the time my own shutdown hook
tries to write a new one.

But more importantly, I'm concerned that I shouldn't be trying to write
new preferences data at all in my shutdown hook.

Can I safely do so? Is it simply a matter of needing to call flush(),
since I can't rely on the Preferences own shutdown behavior to write the
data? Or am I tempting fate here? And if so, is there somewhere in the
Java API documentation that covers this? I did look, but couldn't find
anything specific to this exact scenario.

Thanks!
Pete
 
K

Knute Johnson

Peter said:
I am trying to save some data during user shutdown. To this end, I've
added a ShutdownHook to run when the application shuts down
(Runtime.addShutdownHook()), and in the run() method for the Thread
instance added, I use the Preferences class to save data.

What I found is that unless I call Preferences.flush(), the data wasn't
actually saved. On the one hand, this doesn't seem like an unreasonable
requirement. On the other hand, the documentation _explicitly_ states:

Normal termination of the Java Virtual Machine
will not result in the loss of pending updates
-- an explicit flush invocation is not required
upon termination to ensure that pending updates
are made persistent.

Which to me seems to mean that as long as I don't care when the data is
saved, that it _will_ be saved.

Since it's definitely not being saved, this makes me wonder if it's
kosher to save data to the user preferences at all. On the one hand, I
did get it to work by explicitly flushing the preferences node, but on
the other hand the fact that this was necessary at all suggests that
maybe I shouldn't be trying to access the preferences from my shutdown
hook in the first place.

The documentation for Runtime.addShutdownHook() says, with respect to
the shutdown hook itself:

... They should also not rely blindly upon services
that may have registered their own shutdown hooks
and therefore may themselves in the process of
shutting down.

Since the Preferences class is documented as having at least some degree
of asynchronous behavior, it seems possibly (likely?) that it has its
own shutdown hooks, and thus is relevant to that quote.

At the very least, that would explain why in spite of the Preferences
class saying that you don't need to call flush(), that you actually do
in this case. After all, the Preferences class might already believe
it's done writing all pending preferences out by the time my own
shutdown hook tries to write a new one.

But more importantly, I'm concerned that I shouldn't be trying to write
new preferences data at all in my shutdown hook.

Can I safely do so? Is it simply a matter of needing to call flush(),
since I can't rely on the Preferences own shutdown behavior to write the
data? Or am I tempting fate here? And if so, is there somewhere in the
Java API documentation that covers this? I did look, but couldn't find
anything specific to this exact scenario.

Thanks!
Pete

I looked at the docs and I don't see anything that would cause it not to
work as advertised (except that you say it doesn't). Your assumption
that Preferences uses a shutdown hook to store it's own data and is
missing data you store in another hook is plausible. The following
quote is from the docs on Runtime.addShutdownHook();

"Shutdown hooks run at a delicate time in the life cycle of a virtual
machine and should therefore be coded defensively. They should, in
particular, be written to be thread-safe and to avoid deadlocks insofar
as possible. They should also not rely blindly upon services that may
have registered their own shutdown hooks and therefore may themselves in
the process of shutting down. Attempts to use other thread-based
services such as the AWT event-dispatch thread, for example, may lead to
deadlocks."

I think given the problem you are having that I wouldn't try to update
my Preferences in a shutdown hook, but instead do it earlier, either
when the state changes that you want to keep or before the actual
shutdown starts such as in a WindowListener.
 
P

Peter Duniho

[...]
I think given the problem you are having that I wouldn't try to update
my Preferences in a shutdown hook, but instead do it earlier, either
when the state changes that you want to keep or before the actual
shutdown starts such as in a WindowListener.

I could do the former, though it seems wasteful. Because of that I'd
prefer to leave it until shutdown.

As far as the latter goes, I can't do that because the run-time can be
shut down without actually closing my window. I did try a listener to
respond to the closing event, and never received it in shutdown scenarios
that don't actually involve closing the window (e.g. on the Mac, using the
"Quit" menu item provided by the run-time).

So, I infer from your reply that you feel it would actually be unsafe to
use the Preferences class in a shutdown hook, even calling
Preferences.flush()? Indeed, this was my concern, and it sounds like you
are confirming it (or at least are agreeing that I should be worried :) ).

Pete
 
K

Knute Johnson

Peter said:
[...]
I think given the problem you are having that I wouldn't try to update
my Preferences in a shutdown hook, but instead do it earlier, either
when the state changes that you want to keep or before the actual
shutdown starts such as in a WindowListener.

I could do the former, though it seems wasteful. Because of that I'd
prefer to leave it until shutdown.

As far as the latter goes, I can't do that because the run-time can be
shut down without actually closing my window. I did try a listener to
respond to the closing event, and never received it in shutdown
scenarios that don't actually involve closing the window (e.g. on the
Mac, using the "Quit" menu item provided by the run-time).

So, I infer from your reply that you feel it would actually be unsafe to
use the Preferences class in a shutdown hook, even calling
Preferences.flush()? Indeed, this was my concern, and it sounds like
you are confirming it (or at least are agreeing that I should be worried
:) ).

Pete

Yes I'm agreeing that you have created doubt about whether it would
actually be safe.
 
D

Daniel Pitts

Peter said:
[...]
I think given the problem you are having that I wouldn't try to update
my Preferences in a shutdown hook, but instead do it earlier, either
when the state changes that you want to keep or before the actual
shutdown starts such as in a WindowListener.

I could do the former, though it seems wasteful. Because of that I'd
prefer to leave it until shutdown.
How wasteful? I think that you might be falling into the pitfall of
premature optimization. Unless you change the preferences thousands of
times a second, I wouldn't bother. I think its pretty typical to update
the preferences as the user makes there changes.
As far as the latter goes, I can't do that because the run-time can be
shut down without actually closing my window. I did try a listener to
respond to the closing event, and never received it in shutdown
scenarios that don't actually involve closing the window (e.g. on the
Mac, using the "Quit" menu item provided by the run-time).
Not to mention that a JVM could actually die without running the
shutdown hooks at all.
So, I infer from your reply that you feel it would actually be unsafe to
use the Preferences class in a shutdown hook, even calling
Preferences.flush()? Indeed, this was my concern, and it sounds like
you are confirming it (or at least are agreeing that I should be worried
:) ).
I looked at the WindowsPreferences version, and it doesn't use shutdown
hooks. That doesn't mean anything about the OSX version though.

I really think that you should make the changes when the state changes.
Leave the caching and flushing to the Preference class. If you find
performance problems, *then* you can optimize (with aid from a profiler
ofcourse).
 
P

Peter Duniho

How wasteful? I think that you might be falling into the pitfall of
premature optimization. Unless you change the preferences thousands of
times a second, I wouldn't bother. I think its pretty typical to update
the preferences as the user makes there changes.

I don't disagree with that philosophy per se. It's one I recommend to
others on a regular basis. But the thing I'm saving is a (relatively)
unbounded collection of data objects. The user can add arbitrarily many
of them in the application, and I'm trying to save the entire collection.
It won't change thousands of times a second, but it could change several
times a second (from user input), and the data could be large enough for
this to cause a noticeable slowdown.

Now, a) for most users this collection is likely to be very small (in
fact, in many cases it may never contain anything), and b) there are other
approaches to saving the collection (such as not storing the entire
collection as a single preference object). So it's true that I don't
necessarily need to use this approach.

But doing it this way makes the code a lot simpler, and another philosophy
I recommend is that of simple code. It's harder to put bugs in simple
code. :)
Not to mention that a JVM could actually die without running the
shutdown hooks at all.

A premature exit is always a potential risk. This data isn't what I'd
call "mission critical" :), so I'm willing to live with the increased risk
due to saving data only at exit.
I looked at the WindowsPreferences version, and it doesn't use shutdown
hooks. That doesn't mean anything about the OSX version though.

I found a web page that purported to state the name of the person who
implemented the Preferences class (Joshua Bloch), and where code was
posted that supposedly came from that implementation. In the same code, a
shutdown hook _is_ used, but it's very simple. The code posted would
explain the behavior I saw, but suggests also that there's no harm at all
in using the Preferences class from a shutdown hook oneself, as long as
one does call flush().

In particular, the Preferences implementation in its shutdown hook only
disables the timer used to periodically flush the data to the OS storage,
and then actually does a flush. It doesn't otherwise tear down any
functionlity within the class (which would be my main concern). This is
the link: http://allaboutbalance.com/articles/disableprefs/

Thanks,
Pete
 
R

Roedy Green

Can I safely do so? Is it simply a matter of needing to call flush(),
since I can't rely on the Preferences own shutdown behavior to write the
data?

Calling flush will never hurt. The worst that happens is you slow the
program down a tad.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top