I have an eclipse plugin, which connects to a COM component using Jacob. But after I close the plugin entirely, the .exe file stays hanging in Windows processes.
I use ComThread.InitMTA(true)
for initialization and make sure that SafeRelease()
is called for every COM object I created before closing the app and I call ComThread.Release()
at the very end.
Do I leave something undone?
Had the same problem with TD2JIRA converter. Eventually had to patch one of the Jacob files to release the objects. After that all went smooth.
The code in my client logout() method now looks like this:
try {
Class rot = ROT.class;
Method clear = rot.getDeclaredMethod("clearObjects", new Class[]{});
clear.setAccessible(true);
clear.invoke(null, new Object[]{});
} catch( Exception ex ) {
ex.printStackTrace();
}
The ROT class wasn't accessible initially, AFAIR.
Update
The correct way to release resources in Jacob is to call
ComThread.InitSTA(); // or ComThread.InitMTA()
...
ComThread.Release();
Bad thing though is that sometimes it doesn't help. Despite Jacob calls native method release(), the memory (not even Java memory, but JVM process memory) grows uncontrollably.
Some further suggestions:
Move the call to ComThread.Release()
into a finally
block, otherwise the thread will remain attached if an exception is thrown.
Check that you are calling ComThread.InitMTA
and ComThread.Release
in every thread that uses a COM object. If you forget to do this in a worker thread then that thread will be attached automatically and never detached.
Avoid InitSTA
and stick to InitMTA
. Even when there is only one thread using COM, I have found InitSTA
to be flaky. I don't know how JACOB's internal marshalling mechanism works but I have ended up with "ghost" objects that appear to be valid but do nothing when their methods are invoked.
Fortunately I have never yet needed to modify any code in the JACOB library.
I ran into this issue myself. After messing with initMTA,etc. I found a simple fix - when you start Java add the following to your command line:
-Dcom.jacob.autogc=true
This will cause the ROT class to use a WeakHashMap instead of a HashMap and that solves the problem.
You can also use -Dcom.jacob.debug=true to see lots of informative debug spew and watch the size of the ROT map.