Profiling WebStart Apps with JProfiler on OSX

EJ Technology’s JProfiler is an indispensable tool for tracking down memory leaks and performance bottlenecks. Once a system reaches a certain size, and particularly for systems that have to run for long periods of time, a tool like JProfiler can pay for itself in the space of a single squashed bug.

JProfiler works great under OSX, though purists could probably still find a number of — mostly minor — UI elements that are un-Mac-like. (E.g., menus do not follow Mac conventions and buttons have mnemonics.) A more significant issue is that, at least as of version 4.2.1, there appears to be no way to configure a session for profiling a Web Start application. The documentation suggests that this functionality is available on other platforms, so perhaps the omission is due to perceived uncertainties of Apple’s approach to enforcing a single (per-JDK version) installation of the Java runtime.

Speculated rationale aside, a simple work-around is possible. WebStart is just another Java application, so we can tell JProfiler to launch WebStart as a local application, with the appropriate command line arguments and jars in the classpath to make it download and run the app we actually want to profile. Here are the steps:

1) Choose “New Session” from the “Session” menu, give the session a name, and choose “Local” for the “Session type”.

2) Choose the Java VM that your WebStart application should run under, e.g. “Apple 1.4.2_05”.

3) The concept of a working directory is typically not meaningful for WebStart applications, so you can leave this set to “[startup directory]”.

4) The WebStart launcher application relies on a set of system properties that tell it about the local installation and specify other execution parameters. To set these, something like the following should be entered in the “VM arguments” field:


-Djnlpx.home="/Applications/Utilities/Java/
  Java Web Start.app/Contents/MacOS" 

-Djnlpx.splashport=-1

-Djnlpx.jvm=/System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/
  Home/bin/java 

-Djnlpx.remove=true 

-Djava.security.policy="file:/Applications/Utilities/Java/
  Java Web Start.app/Contents/MacOS/javaws.policy" 

-DtrustProxy=true 

-Djnlpx.heapsize=NULL,NULL 

-Djnlpx.deployment.system.home="/Applications/Utilities/Java/
  Java Web Start.app/Contents/MacOS" 

-Djnlpx.deployment.user.home="/Users/your_user_id/Library/Caches/
  Java Web Start"

Note that you will, at least, need to change your_user_id to the name of the account that you are logged in as. If you are using a version of the Java runtime other than 1.4.2, make sure that the jnlpx.jvm property points to the correct java executable.

JProfiler only gives you a single line in which to enter all of this, so it will probably be easiest if you make any changes in your favorite text editor, then paste the results into the “VM arguments” fields. Just watch out for line-breaks — there shouldn’t be any. Line breaks are shown above for clarity. Here’s the whole mess without them:


-Djnlpx.home="/Applications/Utilities/Java/Java Web Start.app/Contents/MacOS" -Djnlpx.splashport=-1 -Djnlpx.heapsize=NULL,NULL -Djnlpx.jvm=/System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/ Home/bin/java -Djnlpx.remove=true -Djava.security.policy="file:/Applications/Utilities/Java/Java Web Start.app/Contents/MacOS/javaws.policy" -DtrustProxy=true -Djnlpx.deployment.system.home="/Applications/Utilities/Java/Java Web Start.app/Contents/MacOS" -Djnlpx.deployment.user.home="/Users/your_user_id/Library/Caches/Java Web Start"

5) Enter the name of the WebStart launcher application class in the “Main class or executable JAR” field:


com.sun.javaws.Main

Note that this should not be the name of the class you actually want to profile. com.sun.javaws.Main is the class that implements the WebStart launcher. When you launch a Web Start application from a web page, this is the class that handles downloading the JNLP file, retrieving and caching any other jars that are needed, and then running the app.

6) Enter the URL for the WebStart application’s JNLP file in the “Arguments” field. For example, this could be something like:


"http://192.168.1.1/Client.jnlp"

You may want to validate the URL first from the command line, by entering the following in the OSX Terminal:


open "http://192.168.1.1/Client.jnlp"

If the URL is valid, the open command will hand the URL off to your web browser, which will then pass it along to WebStart. Note that if the URL does not contain spaces or other problematic characters you can get by without enclosing it in quotes.

7) The final step is to populate the class path. It is not necessary to include jars or classes for the application that you are profiling, as the WebStart launcher application will take care of downloading those for you. However, the launcher app itself (com.sun.javaws.Main) is not normally included in the default Java runtime classpath.

The jar that you need to add is here:


/Applications/Utilities/Java/Java Web Start.app/Contents/MacOS/javaws.jar

Unfortunately, however, this is inside of an application package, and the JProfiler GUI will not let you navigate into the package to get to the jar. There are several ways to get around this, but my recommendation would be to use a soft link to make jar’s directory accessible by some route other than through the package structure. One way to accomplish this is to execute the following from the OSX terminal:

cd
mkdir javaws_jars
cd javaws_jars
ln -s "/Applications/Utilities/Java/Java Web Start.app/Contents/MacOS/javaws.jar" .

This will create a directory in your home directory named “javaws_jars“, and into it add a link that point to the jar located in “MacOS” directory buried inside the “Java Web Start” application package. (The details of the location and name of the directory are not important, just as long as it is somewhere that you can navigate to in JProfiler. Feel free to put it somewhere else or name it something other than “javaws_jars“.) Note that, due to the way that the Swing JFileChooser — which JProfiler users for jar-picking — works, you cannot simply link the “MacOS” directory. Instead you must link individual files within the directory.

Once this soft link is made, the jar can be accessed as:


/Users/your_user_id/javaws_jars/javaws.jar

Back in the JProfiler “New Session” window, make sure that the “class path” radio button (under “Additional java file path”) is selected, click the green “plus” button, navigate to your home directory, then to the “javaws_jars” directory that you just created, and finally pick the “javaws.jar” file.

8) Click “OK” to save the settings.

When you start the profiled app, the launcher application will load first. It will retreive the JNLP file specified as an argument (step 6, above), download any necessary jar files, then launch the app. If profiling is turned on while these startup steps are executing, they will of course also be included in the stats for profiling. Often this does not matter, but if it does, JProfiler will let you filter out the WebStart classes.

Here shot of a sample JProfiler configuration window with settings for profiling a Web Start application. Note that only a portion of the “VM arguments” setting is visible.