JACOB не освобождает объекты должным образом - PullRequest
2 голосов
/ 11 июня 2009

У меня есть плагин eclipse, который подключается к COM-компоненту с помощью Jacob. Но после того, как я полностью закрыл плагин, файл .exe остается зависшим в процессах Windows.

Я использую ComThread.InitMTA(true) для инициализации и проверяю, что SafeRelease() вызывается для каждого COM-объекта, который я создал, перед закрытием приложения, и я вызываю ComThread.Release() в самом конце.

Я оставляю что-нибудь недоделанным?

Ответы [ 3 ]

6 голосов
/ 19 сентября 2009

Некоторые дополнительные предложения:

  1. Переместите вызов на ComThread.Release() в блок finally, в противном случае поток останется подключенным, если возникнет исключение.

  2. Убедитесь, что вы вызываете ComThread.InitMTA и ComThread.Release в каждом потоке, который использует COM-объект. Если вы забудете сделать это в рабочем потоке, этот поток будет присоединен автоматически и никогда не отсоединится.

  3. Избегайте InitSTA и придерживайтесь InitMTA. Даже когда COM использует только один поток, я считаю InitSTA ненадежным. Я не знаю, как работает механизм внутреннего маршаллинга JACOB, но я получил «призрачные» объекты, которые кажутся действительными, но ничего не делают при вызове их методов.

К счастью, мне никогда не требовалось изменять какой-либо код в библиотеке JACOB.

6 голосов
/ 03 декабря 2009

Я столкнулся с этим вопросом сам. После возни с initMTA и тд. Я нашел простое исправление - при запуске Java добавьте в командную строку следующее: -Dcom.jacob.autogc = истина

Это заставит класс ROT использовать WeakHashMap вместо HashMap, и это решит проблему.

Вы также можете использовать -Dcom.jacob.debug = true, чтобы увидеть множество информативных отладочных эффектов и посмотреть размер карты ROT.

5 голосов
/ 11 июня 2009

Была такая же проблема с конвертером TD2JIRA. В конце концов пришлось исправить один из файлов Джейкоба, чтобы освободить объекты. После этого все прошло гладко.

Код в моем методе logout () клиента теперь выглядит так:

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();
}

Класс ROT изначально не был доступен, AFAIR.

Обновление

Правильный способ освободить ресурсы в Джейкобе - это позвонить

ComThread.InitSTA(); // or ComThread.InitMTA()
...
ComThread.Release();

Плохо то, что иногда это не помогает. Несмотря на то, что Джейкоб вызывает собственный метод release (), память (даже не память Java, а память процесса JVM) бесконтрольно увеличивается.

...