【问题标题】:How to force Javamail to clear its message cache?如何强制 Javamail 清除其邮件缓存?
【发布时间】:2023-03-31 17:29:01
【问题描述】:

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

是否正在进行一些缓存?我不需要再次访问这些消息,除非它是第一次进入。如何强制清除缓存?如何阻止 javamail 泄漏?

【问题讨论】:

    标签: java optimization memory jakarta-mail


    【解决方案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】:

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

      【讨论】:

        【解决方案3】:

        根据docs,您传递了一个布尔值来指示应该删除已删除的消息:

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

        【讨论】:

        • 这不是清除/清空 Javamail 缓存的答案。
        猜你喜欢
        • 1970-01-01
        • 2017-05-19
        • 1970-01-01
        • 2021-09-03
        • 2011-05-02
        • 2016-02-18
        相关资源
        最近更新 更多