Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mac OS 10.9 and higher user preference caching interferes with use of named VM options #31

Open
sreilly opened this issue Nov 4, 2017 · 2 comments
Labels
bug Something isn't working major

Comments

@sreilly
Copy link
Contributor

sreilly commented Nov 4, 2017

Original report by me.


AppBundler provides a way to store JVM options in user preferences by adding a name field to the option tag (in the AppBundler Ant task). I'm trying to use this feature to allow the user of my application to configure the -Xmx option specifically, without having to modify Info.plist and break the code signing signature. Because the maximum heap memory cannot be changed once the JVM is created, the only way to have it set is by having AppBundler pass the -Xmx option to the JVM it creates.

The problem is that Java's default Preferences.userRoot() is implemented to use the Mac OS X defaults user preferences. As discussed in this article https://hints.macworld.com/article.php?story=20130908042828630 starting with Mavericks, the default preferences are cached by the OS and not flushed when an application restarts. Changes to the preferences are flushed periodically by a daemon or when the user logs out or the system is shut down.

Here is a use case demonstrating the resulting problem: The user of my application changes the maximum memory setting, which changes the -Xmx option to use. My application uses the code example in the AppBundler ant task documentation to put the new value of the option in the proper Preferences.userRoot() node. They restart the application and it still uses the old setting until they logout or reboot.

I don't have a solution to the problem yet, and would happy to hear if anyone else does, especially if it is something that can be made part of AppBundler.

@sreilly
Copy link
Contributor Author

sreilly commented Nov 5, 2017

I’m attaching a self-contained demonstration of the problem. Unpack the tarball, cd to the ShowJVMOptions directory. The tools subdirectory contains a appbundler-1.0ea.jar I built from the latest source, but the actual release 1.0ea jar demonstrates the same problem. To build, run the command ‘ant’. That will create ShowJVMOptons.app in the dist directory.

When the application is run it will open a dialog that shows the value of the -Xmx option that was passed to the JVM, the actual max memory value in the JVM, and the value of the option that is currently read by Java from Preferences.userRoot(). The last will be empty if the test application has never been run before. Enter a new value of the -Xmx option in the inout box. Enter only an integer such as 2048, do not enter something like -Xmx2048M. Click on OK to store the new value in userRoot() preference file and exit the program. If you clear the input box so it is blank, or if you click the Cancel button instead of OK, no new value is written to the userRoot() preference file.

Then run the application again. What you will see is that the preference file has the new value, but the option that AppBundler passes to the JVM has not changed.

If you reboot and try it again, you will see that the new preference is finally used by AppBundler.

There is a mismatch between the way Java on Mac OS implements Preferences.userRoot() and the Mac OS implementation of application user preferences which is what AppBundler’s main.m uses.

The Java implementation is in class MacOSXPreferences which directly reads from and writes to the file backing store that Mac OS uses for its preference implementation. Mac OS, on the other hand documents that preferences should be read and written through the OS API and not through direct manipulation of the backing files. That is because the OS makes heavy use of caching the data read from the files.

This mismatch causes the problem with using the AppBundler facility for named JVM options. Java default userRoot preferences look like they are using the Mac OS user preferences facility, but they aren’t really. Therefore main.m shouldn’t use the Mac OS API to read the preferences, it should read and parse the plist file directly just like Java does.

@sreilly
Copy link
Contributor Author

sreilly commented Nov 6, 2017

Correction to my previous comment. MacOSXPreferences does not directly access the plist files. It uses class MacOSXPreferenceFile which has native methods that do the reading and writing of the individual nodes. So it is meant to use the Mac OS CFPreferences, it just doesn't seem to help in this case.
https://github.com/frohoff/jdk8u-jdk/blob/master/src/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java

@sreilly sreilly added major bug Something isn't working labels May 31, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working major
Projects
None yet
Development

No branches or pull requests

1 participant