Tools and applications sometimes hang (do not respond to any mouse or keyboard input) because of an infinite loop, deadlock, or other problem. IBM ® WebSphere® Studio Application Developer (hereafter called Application Developer) is no exception. This article shows you how to identify the component where the hang occurs and determine whether it is due to user error, programming error, or a bug in the product. (Screenshots below are from Application Developer V5.1).
A technique provided by the Java JVM
The Java™ JVM provides the means to produce a javacore at the activation of a combination of keys: pressing Ctrl-Break (on Windows) or Ctrl-\ (on Linux) produces a Signal which will cause the JVM to take a snapshot javacore. The program will continue running unimpeded otherwise. The technique to localize the hang is to produce a few snapshot javacore files and analyze them. We will provide two examples, one in a simple standalone Java program environment, another one running in the Application Developer environment. In both cases, once the program hangs, there is need to press Ctrl-C to terminate the program.
All of our examples are made using the IBM JDK 1.3.1, which is shipped with Application Developer.
Simple standalone Java program
The simple program below (InfiniteLoop.java) will produce a hang caused by an infinite loop:
class InfiniteLoop
{
public static void main(String args[])
{
InfiniteLoop loop=new InfiniteLoop();
loop.hang1();
}
public void hang1()
{
hang2();
}
public void hang2()
{
int i=0;
while (true)
{
i=i+1;
i=i-1;
}
}
} |
Open a command window and compile by executing: javac InfiniteLoop.java. (Use any javac available.) To run, execute:
c:\wsad51\eclipse\jre\bin\java -Djava.compiler= -classpath.
Tips: In the above example, my Application Developer root install is in c:\wsad51, so replace that with your path.
Also, the option -Djava.compiler turns off the JIT off, to avoid an additional level of complexity in the debugging process.
Sample javacore output after simple program hang
After you press Ctrl-Break, look at the resulting javacore files. Each press of Ctrl-Break sends another signal to the JVM and generates a new javacore file. Here is an excerpt from one of the resulting javacore files:
1XMTHDINFO Thread Info NULL ----------- NULL 2XMFULLTHDDUMP Full thread dump Classic VM (J2RE 1.3.1 IBM Windows 32 build cn131-20030711a, native threads): 3XMTHREADINFO "Finalizer" (TID:0x101B4100, sys_thread_t:0x998610, state:CW, native ID:0x94) prio=8 4XESTACKTRACE at java.lang.Object.wait(Native Method) 4XESTACKTRACE at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133) 4XESTACKTRACE at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:148) 4XESTACKTRACE at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:213) 3XMTHREADINFO "Reference Handler" (TID:0x101B4148, sys_thread_t:0x97FD48, state:CW, native ID:0x1E0) prio=10 4XESTACKTRACE at java.lang.Object.wait(Native Method) 4XESTACKTRACE at java.lang.Object.wait(Object.java:429) 4XESTACKTRACE at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:131) 3XMTHREADINFO "Signal dispatcher" (TID:0x101B4190, sys_thread_t:0x97D230, state:R, native ID:0x608) prio=5 3XMTHREADINFO "main" (TID:0x101B41D8, sys_thread_t:0x3E510, state:R, native ID:0xA0) prio=5 4XESTACKTRACE at InfiniteLoop.hang2(InfiniteLoop.java:14) 4XESTACKTRACE at InfiniteLoop.hang1(InfiniteLoop.java:10) 4XESTACKTRACE at InfiniteLoop.main(InfiniteLoop.java:6) NULL ------------------------------------------------------------------------ |
In the excerpt above, the snapshot javacore correctly shows that the JVM is running an instruction in method
InfiniteLoop.hang2() in line 14 of InfiniteLoop.java, which is the while (true) statement. Obviously, since this is a snapshot in time, the line could be any line inside the while loop, such as line 16, 17, or 18.
For an example of how to create a hang using a deadlock, see this Deadlock example.
Quick Application Developer plug-in generation
You can create a plug-in that runs as part of Application Developer and causesa hang to the whole Application Developer application. A quick summary on using an example provided by Application Developer to create a Hello World plug-in which we will modify in order to make it hang Application Developer on demand. (If interested in more details on the Hello World plug-ins sample go to the source: PDE does plugins.) In Application Developer, select File => New => Project. The following window opens:
Click Next, then enter HangIt, then click Next twice. From the available selection of Plug-in code generators, choose Hello World.
Click Next and then click Finish to accept loading plug-ins. Once the plug-in is generated, open the source folder and edit
SampleAction.java as shown below. The goal is to replace the action: instead of a pop-up dialog for Hello World,
we will code an infinite loop and cause a hang. That's why this new plug-in project is called HangIt rather than Hello World.
Exporting the plug-in to a zip file
Follow the steps below to create a zip file containing the HangIt plug-in.
Select to export to a deployable plug-in:
After you click OK, you are prompted with the following choices:
In order to install the plug-in, unzip HangIt.zip into the d:\wsad51
folder, since the Export as deployable plug-in option already created the rest of the \eclipse\plugins\ folder structure.
After you do that and restart Application Developer, you will see the actions from the original Hello World plug-in added to the top menu bar.
(For a more sophisticated way of distributing and installing plug-ins, see
How to keep up-to-date.)
Starting Application Developer from the command line
Important: in order to use the Ctrl-Break technique on Application Developer, you must start it from the command line:
- Open a command prompt window.
- Navigate to the folder where
eclipse.exeis found (in my casec:\wsad51\eclipse). - Execute the following command:
jre\bin\java.exe -Djava.compiler= -cp startup.jar org.eclipse.core.launcher.Main -data d:\Hang |
or
jre\bin\java.exe -Xj9 -Xnojit -cp startup.jar org.eclipse.core.launcher.Main -data d:\Hang |
depending on which JRE you want to use. In the first invocation, IBM JDK 1.3.1 is used, while in the second invocation, J9 is used.
Either one of the above commands will start Application Developer in the d:\Hang workspace.
In each case, -Xjava.compiler= and -Xnojit respectively are used to turn off the JIT compiler,
which is done simply to avoid additional debugging complexity. However, if the hang you are trying to diagnose doesn't happen with JIT turned off,
then you might have found a JIT bug, which is beyond the scope of this article.
If you are using Rational Application Developer,
open a command-line window, change directory to
$RADInstallation\eclipse (in my case
c:\RAD60\eclipse) and execute the following command:
jre\bin\java -Djava.compiler= -Dosgi.adaptor=org.eclipse.core.runtime.adaptor.EclipseAdaptor -cp startup.jar org.eclipse.core.launcher.Main -data d:\MyWorkspace |
Once Application Developer starts, click Loop forever (the hover caption was changed from the original "Hello, Eclipse world" to "Loop forever"
by modifying the plugin.xml file tooltip tag). The action will be invoked and the method Run will execute an infinite loop.
(The button might not show up until you change perspective to the Java perspective.)
With the focus in the Command prompt window, every time you press Ctrl-Break, a javacore will be produced in the same folder where you did the invocation.
Sample javacore output from Application Developer after a hang
After you press Ctrl-Break, look at the resulting javacore files. Each press of Ctrl-Break sends another signal to the JVM and generates a new javacore file. The command window will look something like this:
Here is an excerpt from one of the resulting javacores:
... 1XMTHDINFO Thread Info NULL ----------- NULL 2XMFULLTHDDUMP Full thread dump Classic VM (J2RE 1.3.1 IBM Windows 32 build cn131-20030711a, native threads): 3XMTHREADINFO "Java indexing" (TID:0x101B30F0, sys_thread_t:0x3A61770, state:CW, native ID:0x304) prio=4 4XESTACKTRACE at java.lang.Thread.sleep(Native Method) 4XESTACKTRACE at org.eclipse.jdt.internal.core.search.processing.JobManager.run(JobManage r.java:349) 4XESTACKTRACE at java.lang.Thread.run(Thread.java:513) 3XMTHREADINFO "Finalizer" (TID:0x101B4100, sys_thread_t:0x2ACF110, state:CW, native ID:0x73C) prio=8 4XESTACKTRACE at java.lang.Object.wait(Native Method) 4XESTACKTRACE at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133) 4XESTACKTRACE at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:148) 4XESTACKTRACE at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:213) 3XMTHREADINFO "Reference Handler" (TID:0x101B4148, sys_thread_t:0x975628, state:CW, native ID:0x704) prio=10 4XESTACKTRACE at java.lang.Object.wait(Native Method) 4XESTACKTRACE at java.lang.Object.wait(Object.java:429) 4XESTACKTRACE at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:131) 3XMTHREADINFO "Signal dispatcher" (TID:0x101B4190, sys_thread_t:0x2AC9240, state:R, native ID:0x558) prio=5 3XMTHREADINFO "main" (TID:0x101B41D8, sys_thread_t:0x3E608, state:R, native ID:0x21C) prio=5 4XESTACKTRACE at HangIt.actions.SampleAction.runToHang2(SampleAction.java:58) 4XESTACKTRACE at HangIt.actions.SampleAction.runToHang1(SampleAction.java:52) 4XESTACKTRACE at HangIt.actions.SampleAction.run(SampleAction.java:47) 4XESTACKTRACE at org.eclipse.ui.internal.PluginAction.runWithEvent(PluginAction.java:251) 4XESTACKTRACE at org.eclipse.ui.internal.WWinPluginAction.runWithEvent(WWinPluginAction.j ava:207) 4XESTACKTRACE at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(Ac tionContributionItem.java:456) 4XESTACKTRACE at org.eclipse.jface.action.ActionContributionItem.handleWidgetEvent(Action ContributionItem.java:403) 4XESTACKTRACE at org.eclipse.jface.action.ActionContributionItem.access$0(ActionContribut ionItem.java:397) 4XESTACKTRACE at org.eclipse.jface.action.ActionContributionItem$ActionListener.handleEve nt(ActionContributionItem.java:72) 4XESTACKTRACE at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:81) 4XESTACKTRACE at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:840) 4XESTACKTRACE at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:1838) 4XESTACKTRACE at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:1545) 4XESTACKTRACE at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:1402) 4XESTACKTRACE at org.eclipse.ui.internal.Workbench.run(Workbench.java:1385) 4XESTACKTRACE at org.eclipse.core.internal.boot.InternalBootLoader.run(InternalBootLoader .java:858) 4XESTACKTRACE at org.eclipse.core.boot.BootLoader.run(BootLoader.java:461) 4XESTACKTRACE at java.lang.reflect.Method.invoke(Native Method) 4XESTACKTRACE at org.eclipse.core.launcher.Main.basicRun(Main.java:291) 4XESTACKTRACE at org.eclipse.core.launcher.Main.run(Main.java:747) 4XESTACKTRACE at org.eclipse.core.launcher.Main.main(Main.java:583) NULL ------------------------------------------------------------------------ |
The above trace gives you an accurate idea of where the infinite loop is: somewhere in the method runToHang2() of the class
SampleAction. More specifically, the JVM took a snapshot when the execution was on line 58 of the the
SampleAction class, which is the
while (true) statement. In the case of an infinite loop, the snapshot could be on any line within the loop.
In case of a deadlock, you will most likely see that all threads including the main thread are in some kind of waiting state. In the infinite loop case above, all threads except main are in a waiting state (on a semaphore, or waiting for some event). When all threads are waiting, the trace shows which threads are deadlocked and possibly waiting on the same semaphore.
Another way to do a startup from the command line is to modify the invocation of the Application Developer launcher
(wsappdev.exe) as shown below in the properties of a shortcut icon:
The authors would like to thank Christophe Elek, Software Developer, IBM Toronto Lab, for reviewing this article.
Knowing how to debug and work around hangs in Application Developer applications and in Java applications in general can save you lots of time in your development and testing efforts.
Marius Lut works with the JIT Development group at the IBM Toronto Lab. You can reach Marius at lut@ca.ibm.com
Robert Weisz works with the WebSphere Studio Application Developer Technical Support team at the IBM Toronto Lab. Previously, he worked as a developer on the CDT plug-ins for Eclipse. You can reach Robert at weisz@ca.ibm.com



