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...
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.
The following code will not release all DCOM object references...
Worksheet workSheet = new Worksheet(worksheets.getItem(new Integer(1))); ... com.linar.jintegra.Cleaner.release(workSheet); |
Use this code instead...
Object sheet = worksheets.getItem(new Integer(1)); Worksheet workSheet = new Worksheet(sheet); ... com.linar.jintegra.Cleaner.release(sheet); com.linar.jintegra.Cleaner.release(workSheet); |
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!
The typical way of using this method is to put it in a finally clause at the end of your program...
try { // do some work } finally { com.linar.jintegra.Cleaner.releaseAll(); // only call this once!! } |
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.
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.
The basic structure of your Java code should look like this...
try { com.linar.jintegra.Cleaner.trackObjectsInCurrentThread(); // create an instance of COM component // invoke some methods of COM component ... com.linar.jintegra.Cleaner.releaseAllInCurrentThread(); } |
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.
The basic structure of your Servlet code should look like this...
public class RequestDirector extends HttpServletBase { public void init() throws ServletException { } public void destroy() { com.linar.jintegra.Cleaner.releaseAll(); } // this method can also be doPost or doGet public void method1() { try { com.linar.jintegra.Cleaner.trackObjectsInCurrentThread(); // create an instance of COM component // invoke some methods of COM component ... com.linar.jintegra.Cleaner.releaseAllInCurrentThread(); } } ... } |
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.
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:
final JFrame frame = new JFrame(); final WebBrowser webbrowser = new WebBrowser(); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { public void windowClosed(WindowEvent e) { if (webbrowser != null) { frame.getContentPane().remove(webbrowser); com.linar.jintegra.Cleaner.release(webbrowser); webbrowser = null; } System.gc(); } }); frame.getContentPane().add(webbrowser); frame.pack(); frame.setVisible(true); |
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.