JACOB Version 1.7 implements a new Threading Model that is more compatible with COM apartments. There is also an incompatibility between the Java object lifetime model and that of COM objects. COM Objects live and die by their reference count, whereas Java objects are collected by the Garbage Collector (GC) based on algortihms that are hidden from the user.
In version 1.6 and earlier, JACOB objects which wrapped COM objects
finalize() methods that would call a native
release method which would call a COM
This has many problems. For one thing, the GC may take a long time to kick in and resource consumption may grow. However, the more problematic issue is that finalizers are called from a separate thread, and, as was discussed in the Threading Model document, this can result in COM errors if the object is running in an STA. Even if the object is running in an MTA, the finalizer may decide to run after we have terminated the thread that holds the component, in which case we would get fatal errors and crashes.
In Version 1.7, all JACOB objects which wrap COM objects extend
com.jacob.com.JacobObject. This object has some special
code to register itself with a
which represents a Running Object Table (ROT). This table maps a
Thread to the set of JacobObjects created in that thread. Therefore,
when you call
ComThread.Release(), the ROT checks whether
that thread has created any objects, and these objects are released
by calling their native
release method (which is public).
This lifetime management method ties the lifecycle to the thread's
lifecycle rather than the GC. The JacobObject's still have finalizers,
but they will typically not perform the native
since that has already been called. The native
methods were written such that you can call them multiple times without
worrying - since they zero out the native pointer when called the first
If you choose to call
release methods on your objects
yourself, that is allowed. In that case, when the thread is released
the release calls will be no-ops.
It becomes important for you to call
on any thread before you allow it to exit, otherwise you may get
some random crashes later on in your code.