我使用 Domino 服务器并开发 Java 代理。通常我将外部 jar 文件放入脚本库,但会定期获取 OutOfMemory。我将 jar 从脚本库提取到 jvm/lib/ext。我可以通过 ClassLoader 获取类,但不能通过 import 语句。我应该怎么做才能通过导入语句使其工作?
2 回答
您实际上可以将 jar 显式添加到 Java 代理。请注意,Java 代理默认没有包名,在导入语句中引用包时,您需要引用正确的包名。此处描述了将 jar 导入代理,对于 8.5 版,此处和此处
另外,我怀疑您没有明确清理您是 java 对象。JVM 和 Domino 内存堆之间的连接是“弱的”。因此,您必须对 Domino 对象进行自己的垃圾收集,以保持服务器的内存清洁。这对我来说仍然是黑魔法,但我的理解是,即使代理应该“包含”会话,然后在终止时释放内存,未正确回收的 Domino 对象也会耗尽 Domino 的堆内存。以下是我保持记忆清洁的简单提示:
1/ 将会话对象保存在包装对象中。创建一个包含 Domino 会话对象的类(我称之为 SessionWrapper)。然后只在 NotesMain 方法中声明 SessionWrapper 对象,不要在类级别声明它。这个 SessionWrapper 类需要有它自己的调用 Session.recycle() 的回收方法,并且您需要在 NotesMain 结束时调用它。其原因在第 2 点中进行了解释。如果您不调用 NotesMain 中的任何其他方法,那么您实际上并不需要此包装器。请参阅第 4 点关于回收会话。
2/ 将 SessionWrapper 传递给您需要 Domino 访问的所有方法。基本上,您在这个包装类中将会话作为参数传递。这是因为我们不想在类级别声明会话对象。这并不理想,但可以防止由于将会话类保持在类级别而导致的内存泄漏。
3/ 积极回收。在我看到这个示例循环之前,这对我来说从来没有多大意义
ViewEntryCollection vec = view.getAllEntries();
ViewEntry ve = vec.getFirstEntry();
While (ve!=null) {
ViewEntry veNext = vec.getNextEntry(ve);
// do stuff
ve.recycle;
ve = null;
ve = veNext;
}
看看“ve”对象是如何被回收的,而 veNext 是如何获取下一个对象的。基本上你需要在使用完每个对象后回收它,“getNext”方法实际上不会回收 Domino 堆内存中的对象,如果你不回收它,它就是孤立的,Domino 不会清理运行起来,服务器最终将耗尽 Domino 对象的内存。请注意,我没有回收 veNext。我不需要,因为我分配了 ve => veNext。“ve”将有一个指向同一个 Domino 对象的链接,我在循环结束时调用 recycle ve。从中可以看出,很多java对象可以在后端指向同一个Domino实例对象。如果我尝试在 ve.recycle 之后调用 veNext.recycle,我会收到“对象已被删除或回收”错误。
4/ 在 NotesMain 结束时回收会话。确保在 NotesMain 结束时调用 SessionWrapper.recycle() 以确保将那部分内存释放回服务器。
5/ 确保您为服务器上的 JVM 提供了足够的内存。请参阅此技术说明。还要注意“HTTPJVMMaxHeapSizeSet=1”,这是一个奇怪的设置,可确保内存设置“坚持”。更多关于它的信息在这里。
多年来,IBM 一直没有提供对象的内部清理任务,而这些任务对于消除开发人员的这种开销是非常必要的。然后,您需要显式释放内存,这也会影响性能,但它是稳定性的必要妥协。这些要点绝不是详尽无遗的,但我发现在遵守这些规则时,代理和 servlet 的稳定性大大提高。
- 关闭 Lotus Notes 客户端和设计器。
- 将 JAR 放入本地 jvm/lib/ext。
- 打开 Lotus Notes 客户端和设计器。
现在您可以导入类。