我有一个 Eclipse 插件,它使用 Jacob 连接到 COM 组件。但是在我完全关闭插件后,.exe 文件仍然挂在 Windows 进程中。
我ComThread.InitMTA(true)
用于初始化并确保SafeRelease()
在关闭应用程序之前为我创建的每个 COM 对象调用它,并ComThread.Release()
在最后调用。
我会留下一些未完成的事情吗?
一些进一步的建议:
将调用移动ComThread.Release()
到一个finally
块中,否则如果抛出异常,线程将保持连接状态。
检查您是否正在调用ComThread.InitMTA
并ComThread.Release
在每个使用 COM 对象的线程中。如果您忘记在工作线程中执行此操作,则该线程将自动附加并且永远不会分离。
避免InitSTA
并坚持InitMTA
。即使只有一个线程使用 COM,我也发现InitSTA
它很不稳定。我不知道 JACOB 的内部编组机制是如何工作的,但我最终得到了看起来有效但在调用它们的方法时什么都不做的“幽灵”对象。
幸运的是,我从未需要修改 JACOB 库中的任何代码。
我自己遇到了这个问题。在搞乱 initMTA 等之后。我找到了一个简单的修复方法 - 当您启动 Java 时,将以下内容添加到您的命令行:-Dcom.jacob.autogc=true
这将导致 ROT 类使用 WeakHashMap 而不是 HashMap,从而解决了问题。
您还可以使用 -Dcom.jacob.debug=true 查看大量信息丰富的调试信息并查看 ROT 映射的大小。
TD2JIRA 转换器也有同样的问题。最终不得不修补其中一个 Jacob 文件以释放对象。之后一切顺利。
我的客户端 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();
}
AFAIR 最初无法访问 ROT 类。
更新
Jacob中释放资源的正确方法是调用
ComThread.InitSTA(); // or ComThread.InitMTA()
...
ComThread.Release();
但不好的是,有时它没有帮助。尽管 Jacob 调用了本地方法 release(),但内存(甚至不是 Java 内存,而是 JVM 进程内存)还是无法控制地增长。