We have a Swing app that processes relatively large amounts of data. For instance we currently process CSV files with millions of rows of data. For the reasons of performance and simplicity we just keep all of the data in memory. However different users will have different amounts of data they need to process as well as different amounts of RAM. When creating the installer, of course we need to specify the heap size. Is there any easy way to allow the user to specify the heap without them needing to hand edit a configuration or .bat file? I'm guessing not all users would be comfortable with this.
I've seen one example where an app specified three different shortcuts each with a different amount of memory specified. This could work but I would like an option that is more flexible. The user could then just choose the one that would work best for them.
I recommend having something similar to IntelliJ. It brings up a configuration dialog when an OutOfMemoryException occurs. This dialog allows the user to configure the heap size and stores it to idea.exe.vmoptions
. You would need to sub the contents of the file into the java/javaw launch command or have one Java program bootstrap and launch the real one.
A really cool variant on this is to suggest a memory size based on the data size. The user really has no way of knowing how much memory your program needs so any guidance you can provide in selecting the value will help them immensely.
It is extremely important in support of this solution that you expect and handle OutOfMemoryExceptions in a way that avoids data corruption!
I would write a short startup.jar with very few fixed memory settings starting from a script. In turn startup.jar will start your target app with Runtime.exec() and adjusted parameters.
You end up in 2 JVM instances that spend more memory than only one JVM. But if your application will spend a lot of memory anyway the first JVM does not matter.
The main idea would be this:
- Launch your main application through a shell script similar to this:
@echo off
setlocal
REM This reads the JVM command line options from a user configuration file
for /f %x in (%HOMEDRIVE%%HOMEPATH%\myapp.config) do set JVM_OPTIONS=%x
REM Important: call javaw and not java
javaw -jar myApp.jar %JVM_OPTIONS%
endlocal
- In your Swing application, have a menu option Memory settings.... When the user selects that, parse the user's configuration file and populate a settings dialog so that the user can change whatever it is appropiate. When the user clicks Apply or Ok, overwrite the user configuration file with command line options according to the user's selected settigns (in your case,
-Xmx
), and show a message saying something like Restart the application to apply these settings.
catch the outofmemory excpetion , lauch a swing user dialog to set the memory limit, pass this value to a thread that uses Runtime.exec() restart the application using java -cp lib's jar vmoptions that will launch a new jvm with memory size specified to user.sample:
Runtime.getRuntime().exec("java -cp
-Xms2560m -Xmx2560m -XX:NewSize=32M -XX:MaxPermSize=256M -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseParNewG launch.jar");
You did not mention how you are creating the installer. If you do not already use it, I suggest using NSIS. The documentation is good and it has a plugin for eclipse. You can use the wizard to generate the nsi file and then edit it manually for the options that are not available with the wizard.
As to your current requirement, simply add a page to the installer for the options and based on the option selected, copy the correct system properties file to the user settings folder that you can use to start your program. I am not sure if its possible but I think once the program is installed, the user can re-run the installer and select a different option.