如何强制Javamail清除其邮件缓存?

时间:2009-09-23 15:25:29

标签: java optimization memory javamail

我正在运行使用Javamail的服务器。它有一个带有IMAP IDLE的计数监听器,这样当一个新邮件进来时,就会执行某段代码。新消息列表作为参数提供给我的监听器。我阅读了它的信息并完成了它。一切都很好,除了我的服务器泄漏了大量内存!我做了堆转储,发现类[Lcom.sun.mail.imap.IMAPMessage正在使用大量内存。看来com.sun.mail.imap.MessageCache对象引用了一个IMAPMessage数组。

是否有一些缓存?我不需要再次访问这些消息,除了它第一次进来。如何强制缓存清除?如何阻止javamail泄露?

3 个答案:

答案 0 :(得分:1)

根据docs,您使用布尔值表示应删除已删除的邮件:

message.setFlag(Flags.Flag.DELETED, true);
folder.close(aBoolean);
store.close();

答案 1 :(得分:1)

我在Javamail论坛中找到了这个引用 How to force Javamail to clear its message cache?

然后做了一些挖掘。虽然我还没有找到删除或缩小“缓存”的方法,但我发现该缓存的最大部分是邮件的标题。 IMAPMessage中有两个标题副本,一个是它的副本,另一个是它填充的MIMEMessage。现在,当您想要清除此信息时会遇到麻烦,因为它们只能让您访问清除IMAPMessage中的信息。 MIMEMessage中的标头无法清除。此外,它们无法移除。以下是InternetHeaders.remove(String)

中的代码
/**
 * Remove all header entries that match the given name
 * @param   name    header name
 */
public void removeHeader(String name) { 
for (int i = 0; i < headers.size(); i++) {
    InternetHeader h = (InternetHeader)headers.get(i);
    if (name.equalsIgnoreCase(h.getName())) {
    h.line = null;
    //headers.remove(i);
    //i--;    // have to look at i again
    }
}
}

无论如何,我可以通过输入并清空所有这些值来显着减少MessageCache存储的内存。

Field headerField = MimeMessage.class.getDeclaredField("headers");
headerField.setAccessible(true);
InternetHeaders headers = (InternetHeaders) headerField.get(imapMessage);
if (headers != null) {
   Enumeration<?> allHeaders = headers.getAllHeaders();
   ArrayList<String> headerNames = new ArrayList<String>();
   while (allHeaders.hasMoreElements()) {
       Header header = (Header) allHeaders.nextElement();
       headerNames.add(header.getName());
   }
   for (String headerName : headerNames) {
       headers.setHeader(headerName, null);
   }
}

不是最漂亮的,但它会将一个文件夹的内存占用从40MB减少到20MB。我要看看是否有其他方法可以做到这一点。理想情况下,我认为我会创建自己的重写IMAPMessage类,但这似乎很难掌握。

答案 2 :(得分:0)

如果您不喜欢Sun,可以尝试其他Java Mail实现。 GNU Classpath有一个(http://www.gnu.org/software/classpathx/javamail/javamail.html