Tracing and Profiling Swing/AWT Applications
 



Introduction
With the of JXInsight 4.1, developers and testers will be able trace and profile Swing/AWT applications. It will be possible to trace a single mouse click across local and remote threads. This article will show how JXInsight can solve one of the biggest testing pains for Swing developers - the disconnect between the call stack of the thread posting an event to the AWT EventQueue and the call stack of the thread dispatching the event.


Classes and Concepts

In Swing/AWT applications UI component events are posted to a shared instance of java.awt.EventQueue. The EventQueue class is platform-independent class that queues events, both from the underlying peer classes and from trusted application classes. AWTEvents are then removed from the queue by an instance of java.awt.EventDispatchThread via the method EventQueue.getNextEvent and then processed by the same thread by calling the method EventQueue.dispatchEvent. It is this disconnect in the lifecycle of an event that makes it difficult to determine the origin for the execution of business logic or application workflow. This is even more of a problem with applications increasily using helper methods in javax.swing.SwingUtiliities to schedule the execution of units of work (java.lang.Runnable) in the AWT event processing thread via the EventQueue. This is done to improve the responsiveness of UI applications.


Integration
Step 1 - Install JXInsight Auxiliary LookAndFeel
To integrate the JXInsight Swing/AWT trace extension add the following system property to the command line of the Swing/Application application.
-Dswing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel

Alternatively edit the swing.properties file in $JREHOME/lib/swing.properties adding the following line
swing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel

Step 2 - Setup Client Classpath
The trace extension is packaged in both jxinsight-all.jar and jxinsight-core.jar jar files. Place either jxinsight-all.jar or jxinsight-core.jar on the classpath of the Java application.

Windows
java -Xrunjdbinsight -cp jxinsight-all.jar;..... -Dswing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel %AppClass%
java -Xrunjdbinsight -cp jxinsight-core.jar;..... -Dswing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel %AppClass%
Unix
java -Xrunjdbinsight -cp jxinsight-all.jar:..... -Dswing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel $AppClass
java -Xrunjdbinsight -cp jxinsight-core.jar:.... -Dswing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel $AppClass

If an Java application is started using java -jar AppJar.jar then use the following
Windows
java -Xrunjdbinsight -Xbootclasspath/a:jxinsight-all.jar -Dswing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel -jar %AppJar%
java -Xrunjdbinsight -Xbootclasspath/a:jxinsight-core.jar -Dswing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel -jar %AppJar%
Unix
java -Xrunjdbinsight -Xbootclasspath/a:jxinsight-all.jar -Dswing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel -jar $AppJar
java -Xrunjdbinsight -Xbootclasspath/a:jxinsight-core.jar -Dswing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel -jar $AppJar


Step 3
- JXInsight Management Console
After the client application has been started startup the JXInsight management console and connect to the host and port number (default is 1515) of the JXInsight agent embedded within the Swing/AWT application.


Sample Swing Application #1: JXInsight Management Console (Mac OSX)
To profile the JXInsight management console, which is a Java Swing application, first create an empty call stack filters configuration file, nofilters.config, in ${jxinsight-install-root}/filters directory. This file is created because by default JXInsight will filter out all javax.swing.* and java.awt calls from recorded trace call stacks.

Create a copy of the jxinsight-console.sh startup script changing the exec command line to

exec ${JAVA} -Dcom.apple.mrj.application.apple.menu.about.name="JXInsight Console (Traced) " -Xms64M -Xmx320M -Xrunjdbinsight -Djxinsight.server.transmitter.enabled=false -Djxinsight.process=server -Djxinsight.server.tracer.enable=true -Djxinsight.server.profiler.timeline.autostart=true -Djxinsight.server.callstack.filters.config=filters/nofilters.config -Djxinsight.server.tracer.ext.swing.awt.queue.componentpath.include=true -Dswing.auxiliarylaf=com.jinspired.jxinsight.trace.ext.swing.LookAndFeel -jar lib/jxinsight-console.jar -console


After starting up the traced version of the management console and loading some snapshots start up another management console using the non-traced startup script and connect to the traced console by creating a new server with host=localhost and port=1515. Switch to the Traces perspective within the analysis mode within the Profile analysis mode. The screen shot below shows the traces generated by the traced JXInsight management console viewed inside the non-traced JXInsight management console. The sequence of trace nodes enclosed in the client-trace brackets (< and >) is the trace stack that was active when the AWTEvent was posted to the EventQueue. The sequence is inserted into the trace stack of the traced call - EventQueue.dispatchEvent.




The following screen shot shows the timeline analysis for the Swing traces generated by the JXInsight management console session. The postEvent trace in the bottom row (row = thread) results in a dispatchEvent trace shown in the top row. The bar chart at the top of the graphic shows the concurrent execution of threads posting and dispatching the event.




Sample Swing Application #2: HP OpenView Service Desk 5.0 Console
JXInsight 4.1 ships with an custom trace extension for HP OpenView ServiceDesk 5.0 that supports distributed tracing from client-to-server-to-database. The following screen shot shows the client side traces generated by a traced version of the Service Desk 5.0 Swing application console. The Remote Traces Table view shows the remote traces found in the clustered snapshot (client and server snapshots have been merged) for the selected trace, postEvent, in the Trace Table view.




The following screen shot of the sever-side traces within the HP OpenView application server shows the client trace inserted into the server-side request trace stack. Please note that there are in fact 2 client traces. One client trace (postEvent) is embedded in another client trace (dispatchEvent) because within the HP OpenView ServiceDesk 5.0 console the sending of the request originated from an event posted to the AWT EventQueue from another thread. This shows the powerful and unique distributed tracing capabilities of JXInsight tracking a request across multiple threads and processes.




Switching the bottom view site to Client Trace Points Table view makes it is extremely easy to pinpoint the actual client side call stack for server side request even when the request was generated indirectly by another thread within a Java Swing application. In the example below the AppServerEntity.find operation was initiated by the placing of a AWTEvent on the EventQueue by the OVSwingUtilities class. When the AWTEvent was dispatched by the enclosing of a java.lang.Runnable within an java.awt.InvocationEvent a call was on the client-side proxy of the AppServerEntity component. Prior to the transmission of the remote request the client trace stack was dynamically inserted into the payload of the request and then extracted from within the server and inserted into the trace stack of the server side processing thread.




William Louth, JXInsight's Product Architect