【发布时间】:2010-11-02 02:27:51
【问题描述】:
我有一个 Eclipse 插件,它使用 Jacob 连接到一个 COM 组件。但是在我完全关闭插件后,.exe 文件仍然挂在 Windows 进程中。
我使用ComThread.InitMTA(true) 进行初始化,并确保在关闭应用程序之前为我创建的每个COM 对象调用SafeRelease(),并在最后调用ComThread.Release()。
我会留下一些未完成的事情吗?
【问题讨论】:
我有一个 Eclipse 插件,它使用 Jacob 连接到一个 COM 组件。但是在我完全关闭插件后,.exe 文件仍然挂在 Windows 进程中。
我使用ComThread.InitMTA(true) 进行初始化,并确保在关闭应用程序之前为我创建的每个COM 对象调用SafeRelease(),并在最后调用ComThread.Release()。
我会留下一些未完成的事情吗?
【问题讨论】:
一些进一步的建议:
将对ComThread.Release()的调用移动到finally块中,否则如果抛出异常,线程将保持连接状态。
检查您是否在使用 COM 对象的每个线程中调用 ComThread.InitMTA 和 ComThread.Release。如果您忘记在工作线程中执行此操作,则该线程将自动附加并且永远不会分离。
避免使用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();
}
最初无法访问 ROT 类,AFAIR。
更新
Jacob中释放资源的正确方法是调用
ComThread.InitSTA(); // or ComThread.InitMTA()
...
ComThread.Release();
但不好的是,有时它无济于事。尽管 Jacob 调用了本机方法 release(),但内存(甚至不是 Java 内存,而是 JVM 进程内存)却无法控制地增长。
【讨论】: