Garbage Collection: Releasing Java References to COM Objects

Contents

  1. Introduction
  2. com.linar.jintegra.Cleaner
  3. com.linar.jintegra.Cleaner.releaseAll()
  4. trackObjectsInCurrentThread() / releaseAllInCurrentThread()
  5. Example: Working with Microsoft Excel
  6. Example: Embedded ActiveX Control in Java Frame
  7. DCOM Pinging

1. Introduction

When accessing COM objects from Java, J-Integra® creates a Java object reference for each COM object. When these DCOM object references go out of scope (i.e. they can no longer be accessed by other objects), the JVM markes them for garbage collection. When such a reference is garbage collected, J-Integra® adds it to an internal list, and every ten seconds a J-Integra® daemon thread releases the actual COM objects that these batched DCOM object references refer to.

In summary, the overall process works like this...

  1. J-Integra® creates a Java object reference to a COM object.
  2. The object reference goes out of scope.
  3. The JVM marks the object reference for garbage collection.
  4. Garbage collector runs:

2. com.linar.jintegra.Cleaner

J-Integra® will always clean up its DCOM object references automatically. However, waiting for COM objects to be automatically released can be problematic due to the nature of Java garbage collection. The frequency of garbage collection can depend on many things, including which JVM you are using and how memory-intensive your application is. Sometimes the garbage collector may not have a chance to run very often. When this happens, your DCOM object references can build up without ever being released, using up valuable memory and resources. To avoid this, J-Integra® provides a mechanism to explictly release a DCOM object reference without having to wait for garbage collection...

Remember, DCOM object references can have underlying DCOM object references associated with them. If you do not release the underlying DCOM object references in addition to the parent reference, some of the COM objects will stay in memory. The following Excel example will help demonstrate this.

3. com.linar.jintegra.Cleaner.releaseAll()

To ensure that all DCOM object references are released when your application shuts down, you should always call the following line right before the JVM exits...

This will release any DCOM object references (process wide) that have not already been released through garbage collection. Once you have called this method you will no longer be able to make use of any COM objects accessed via J-Integra®, so make sure you only call this once at the end of your program!

There is also a J-Integra® property called JINTEGRA_RELEASEALL_SHUTDOWN_HOOK which, if set, will automatically release any DCOM object references if the JVM were to abruptly crash or exit.

4. trackObjectsInCurrentThread() / releaseAllInCurrentThread()

These two methods will track and then release all DCOM object references to COM objects in the current thread. It is important to use these methods in Applets/Servlet/JSP/EJB and multithreading applications, but you can also use them in other types of Java clients as well.

However, in Servlets, do not invoke trackObjectsInCurrentThread in init() or invoke releaseAllInCurrentThread in destroy(). Instead, invoke releaseAll() in destroy(). This is because destroy() is only invoked when the application server is shut down.

5. Example: Working with Microsoft Excel

Many customers ask us why the EXCEL.EXE process stays in memory even though they have called Application.quit() and their Java client application has shut down cleanly. When this happens, the only way to shut down the EXCEL.EXE process is to open Task Manager and manually kill it. Here are a few suggestions to avoid this problem.

  1. Make sure your Java code calls com.linar.jintegra.Cleaner.releaseAll() just before your JVM exits. Alternatively, you can use the JINTEGRA_RELEASEALL_SHUTDOWN_HOOK property when running your Java application.

  2. After calling Application.quit(), you can call com.linar.jintegra.Cleaner.release(Application). This tells J-Integra® to release its reference to the Excel Application and causes the EXCEL.EXE process to terminate (assuming there are no other references to it).

  3. As with any J-Integra® application, you can always allow the DCOM object references to get released automatically via garbage collection. After calling Application.quit(), the Application object will get marked for garbage collection once it goes out of scope. Alternatively, you can explicitly mark it for garbage collection by setting it to null and explicitly invoke garbage collection:
    Application = null;
    System.gc();
    Once the object is garbage collected, J-Integra® will release the EXCEL.EXE process (assuming there are no other references to it).

6. Example: Embedded ActiveX Control in Java Frame

To garbage collect an ActiveX Control that is embedded in a Java frame, make sure that the ActiveX Control is removed from the Java frame first. For example:

7. DCOM Pinging

When running in DCOM mode, the J-Integra® runtime sends DCOM ping messages (as per the DCOM protocol) to tell the COM server that the client is still alive. According to the DCOM specification, DCOM clients send these ping messages every two minutes. If three consecutive ping intervals (six minutes) goes by without the COM server receiving a ping message, the server assumes the client has either crashed or become unreachable due to a network failure, and will release and cleanup its references. See MSDN article DCOM Remote Protocol Specification for details.