JACOB doesn't release the objects properly
Asked Answered
J

3

3

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?

Janey answered 11/6, 2009 at 10:56 Comment(0)
E
5

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.

Est answered 11/6, 2009 at 12:11 Comment(3)
Thanks Vladimir for your feedback. I used a test app, and .exe is closed right after test app closure. For Jacob, your solution seems to work, .exe is removed within 5 minutes, and no memory usage changes are seen during that time in task manager.Is 5 minute duration normal? maybe some Jacob issue?Janey
I have to admit that the solution was intuition-based (after many tries), and I have no knowledge that supports it or explains it. :(Est
how did you patch the jacob files, do you remember?Flack
C
6

Some further suggestions:

  1. Move the call to ComThread.Release() into a finally block, otherwise the thread will remain attached if an exception is thrown.

  2. 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.

  3. 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.

Contiguity answered 19/9, 2009 at 10:14 Comment(1)
Even with InitMTA and correct opening/closing sequence, I found that memory is consumed pretty fast. As the result, what I do now is to spawn a child process handling DCOM communication, and talk to it via text protocol. When a specific number of calls passed, I kill it mercilessly and respawn it. The server I use allows that, thankfully.Est
T
6

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.

Titre answered 2/12, 2009 at 21:14 Comment(0)
E
5

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.

Est answered 11/6, 2009 at 12:11 Comment(3)
Thanks Vladimir for your feedback. I used a test app, and .exe is closed right after test app closure. For Jacob, your solution seems to work, .exe is removed within 5 minutes, and no memory usage changes are seen during that time in task manager.Is 5 minute duration normal? maybe some Jacob issue?Janey
I have to admit that the solution was intuition-based (after many tries), and I have no knowledge that supports it or explains it. :(Est
how did you patch the jacob files, do you remember?Flack

© 2022 - 2024 — McMap. All rights reserved.