Low-Level Java/COM Integration
 In this topic

*Reference Counting

*Supporting Multiple Interfaces

*How IDispatch Is Implemented

*Implementing COM Interfaces

*Parameters Passed by Reference

 

Java & Native Code    PreviousJava/ComNext
Low-Level Java/COM Integration     Previous Java/Com Next

 


Implementing COM Objects

Suppose you want to implement a COM object in Java. You need to understand how the VM for Java takes care of reference counting, how you can implement multiple interfaces on a Java object, and how QueryInterface and IDispatch are implemented. These topics are discussed in the sections that follow.

Reference Counting

Reference counting is handled automatically in Java. There is no need to call IUnknown::AddRef when creating a new reference to an object, nor do you need to call IUnknown::Release when you're finished using a reference to an object. The Java garbage collector automatically keeps track of how many references there are to an object. In practice, however, you may need to explicitly release some COM objects to ensure a timely release of shared resources. You can use the com.ms.com.ComLib.release method to force Java to release all its reference counts on a COM object.

Supporting Multiple Interfaces

COM objects can support multiple interfaces and Java supports multiple interfaces on objects. This is probably the most important reason that Java/COM integration works so well. Consider the previous robot example, but the COM Robot class (CLSID_Robot) implements an interface called IRobotDiagnostics in addition to IRobot. The IRobot interface is used to control what the robot does and IRobotDiagnostics determines the status of the robot.

The following C++ code makes use of both interfaces. First, the robot is instructed to move forward 10 units, and then turn left 90 degrees, using the IRobot interface. The following example then uses QueryInterface for IRobotDiagnostics, and uses that interface to tell the robot to display a status message:


//  Error handling has been omitted for brevity.
IRobot* probbie = NULL;
IRobotDiagnostics* probbieDiag = NULL;
CoCreateInstance(CLSID_Robot, NULL, CLSCTX_SERVER, IID_IRobot, (void**)&probbie);
probbie->GoForward(10);
probbie->Turn(-90);
probbie->QueryInterface(IID_IRobotDiagnostics, (void**)&probbieDiag);
probbie->OutputStatusMessage();
probbieDiag->Release();
probbie->Release();

The same code, written in Java, would look like this:


import robocorp.bots.*;
Robot robbie = new Robot();
IRobotDiagnostics robbieDiag = null;
robbie.GoForward(10);
robbie.Turn(-90);
robbieDiag = (IRobotDiagnostics)robbie;
robbieDiag.OutputStatusMessage();

Because the Microsoft VM provides the implementation of IUnknown, there is no need to implement QueryInterface. The assignment statement does the implicit QueryInterface for IRobotDiagnostics (this is very similar to how QueryInterface is supported in Visual Basic version 4.0).

An explicit cast to the interface is necessary just as it is necessary in normal Java interfaces. An exception is thrown if the object does not support the interface you want. The standard Java instanceof operator can be used to determine whether a given interface is supported.

How IDispatch Is Implemented

When implementing automation objects in Java, you can use automatic IDispatch. The VM implements IDispatch automatically for almost all Java objects. This means that a tool, such as jactivex, is no longer necessary simply to script a Java object from an automation controller such as Visual Basic or Microsoft® Visual Basic® Scripting Edition (VBScript). To implement a simple automation object in Java, you need to do the following things:

  1. Implement the Java object and compile it.
  2. Register it using javareg.
  3. Ensure that the Java class is visible in the CLASSPATH environment variable.

Implementing COM Interfaces

Normally (in the absence of COM), when implementing an interface on a Java class, the interface being implemented is either declared within the code module (file) where the implementation occurs or in an external .class file, which is imported through the import statement. You cannot define an interface using the interface declaration and import the same interface's declaration from a .class file. This rule also holds true for COM interfaces. Therefore, you will never see a COM interface defined by Java. Instead, a COM interface is defined in IDL, compiled into a type library, and imported into Java as though it were a standard Java .class file.

To implement COM interfaces on a Java class, use the implements modifier on the class declaration with a list of interface names and provide method bodies for each method in the interfaces (excluding QueryInterface, AddRef, and Release).

The following example shows the IRobot interface described in IDL:


[ object, uuid(6C6971D5-8E69-11cf-A54F-080036F12502)]
interface IRobot : IUnknown
{
	...
	HRESULT OutputStatusMessage([out, retval]BOOL* pRetVal);
	...
};

If the IDL file was compiled into the robocorp/bots.tlb type library, the following Java code could be written to implement a robot object:


import robocorp.bots.*;
class RogerRobot implements IRobot
{
	...
	boolean OutputStatusMessage(void)
	{
		return VoiceBox.Speak(CurrentStatus());
	}
	...
}

Every Java class automatically implements IUnknown and IDispatch. The dispinterface implemented by the IDispatch interface, which Java provides, contains the public methods that are on the default interface for the class. For example, the following Java class implements an IDispatch interface, which supports MethodA and MethodB:


class Example 
{
	public void MethodA(void)
        { ... }

	public void MethodB(int x) 
	{ ... }
}

At run time, the Microsoft VM automatically provides type information for this IDispatch implementation (using IDispatch::GetTypeInfo), so clients can avoid the overhead of using IDispatch::GetIDsOfNames to do late binding. Since all Java objects are COM objects, nothing else is required.

Parameters Passed by Reference

COM interface methods can have parameters that pass simple types such as integers, floating point values, and characters by reference. In most cases these parameters are "out" parameters. For example, the COM method MySample has the following signature:


HRESULT MySample([in] long l, [out] long* Out1, [out, retval] long* retval);

However, Java does not support parameters that are references to the intrinsic data types, and it does not support pointers. But you can still call MySample from Java. Reference types are mapped to one-element arrays by the Microsoft VM. Therefore, you can retrieve a reference in the following way:


int A;
int B[] = new int[1];
A = MySample(42, B);
System.out.println("A = " + A + " and B = " + B[0]);

Top © 1998 Microsoft Corporation. All rights reserved. Terms of use.