Debugging Java Classes

Debug your Java classes as thoroughly as possible before converting the Java classes into MTS components. Note that once your Java class is converted into an MTS component, it is not possible to step through the code in the Visual J++ debugger, or in any current debugging tool as well.

Sidebar: Using Visual J++ to Debug Java Classes

Microsoft Visual J++ (VJ++) provides a Java debugger that you can use to set breakpoints in your code. Note that when you are using VJ++ to debug, if you set a breakpoint in a Java source file before starting the debugging session, Visual J++ may not stop on the breakpoint. For performance reasons, the debugger preloads only the main class of your project. The main class is either the class with the same name as the project or the class you specify in VJ++. If you use the editor to set breakpoints in other classes before the classes are loaded, the breakpoints are disabled.

You can choose one of the following options to load the correct class so that the debugger stops at breakpoints.

When a method has one or more overloaded versions and shows up as a called method in the Call Stack window, the type and value for the parameters are not displayed in some cases. It appears as though the method takes no parameters. This occurs when the called method is not defined as the first version of the overloaded method in the class definition. For example, see the following class definition:

public class Test
   {
       int method(short s)
       {
           return s;
       }

       int method(int i)
       {
           return i;
       }
   }

If you were looking at a call to the second version of the method in the Call Stack window, it would appear without the type and value for the method:

method()

To view the method’s parameters, change the order of the method overloads so that the method that you are currently debugging is first in the class definition.

printf-style Debugging

You can use printf-style debugging to debug your Java classes without using a debugger. printf-style debugging involves including status text messages into your code, allowing you to "step through" your code without a debugger. You can also use printf-style debugging to return error information. The following code shows how you can add a System.out.println call to the try clause of the Hellojtx.HelloObj.SayHello sample.

try
{    
System.out.println("This message is from the HelloObj implementation");
    result[0] = "Hello from simple MTS Java sample";
    MTx.GetObjectContext().SetComplete();
    return 0;
}

The client must be a Java client class, and you must use the JVIEW console window to run that class. Note that you need to configure your component to run in the process of its caller, which is in this case JVIEW. Otherwise, this debugging technique results in your component running in the MTS server process (mtx.exe), which would put the println output in the bit bucket rather than the JVIEW console window.

Use the MTS Explorer to configure your component to run in the caller's process by following these steps.

  1. Right-click the component.
  2. Click the Properties option.
  3. Click the Activation tab and clear the In a server process on this computer checkbox.
  4. Select the In the creator’s process... checkbox.
  5. Reload the Client class. Your component's println calls will be visible in the JVIEW console window.

Using the AWT Classes

You can also use the AWT (Abstract Window Toolkit) classes to display intermediate results, even if your component is running in a server process. The java.awt package provides an integrated set of classes to manage user interface components such as windows, dialog boxes, buttons, checkboxes, lists, menus, scrollbars, and text fields.

The following example demonstrates how to use the AWT classes to display intermediate results in a dialog box:

import java.awt.*;

public final class MyMessage extends Frame
{

    private Button closeButton;
    private Label textLabel;

    // constructor
    public MyMessage(String msg)
    {
        super("Debug Window");

        Panel panel;

        textLabel = new Label (msg, Label.CENTER);
        closeButton = new Button ("Close");

        setLayout (new BorderLayout (15, 15));
        add ("Center", textLabel);

        add ("South", closeButton);

        pack();
        show();
    }

    public boolean action (Event e, Object arg)
    {

        if (e.target == closeButton)
        {
            hide();
            dispose();
            return true;
        }

        return false;
    }

}

Asynchronous Java Garbage Collection

Note that garbage collection for Java components is asynchronous to program execution and can cause unexpected behavior. This behavior especially affects MTS components that perform functions such as enumerating through the collections in the catalog because the collection count will be too high (garbage collection is not synchronized). To force synchronous release of references to COM or MTS objects, you can use the release method defined in class com.ms.com.ComLib.

Example:

Import com.ms.com.ComLib
…
ComLib.release(someMTSObject);

This method releases the reference to the object when the call is executed. Release the object reference when you are sure that the reference is no longer needed. Note that if you fail to release the reference, an application error is not returned. However, an incorrect collection count results because the object reference is released asynchronously when the garbage collector eventually runs.

You can also force the release of your reference and not call that released reference again.

Example:

myHello = null;
    System.gc();

Note that forcing the release of an object reference consumes extensive system resources. It is recommended that you use the release method defined in com.ms.com.ComLib class to release references to MTS objects in a synchronous fashion.