3 Stimmen

Wie kann ich Javamail zwingen, seinen Nachrichten-Cache zu löschen?

Ich betreibe einen Server, der Javamail verwendet. Er hat einen Count-Listener mit IMAP's IDLE, so dass, wenn eine neue Mail eintrifft, ein bestimmtes Stück Code ausgeführt wird. Die Liste der neuen Nachrichten wird meinem Listener als Parameter übergeben. Ich lese die Informationen daraus und bin damit fertig. Alles ist gut, außer dass mein Server eine Menge Speicher leckt!! Ich habe einen Heap-Dump durchgeführt und festgestellt, dass die Klasse [Lcom.sun.mail.imap.IMAPMessage] sehr viel Speicher verbraucht. Es scheint, dass ein Array von IMAPMessage durch das Objekt com.sun.mail.imap.MessageCache referenziert wird.

Gibt es eine Zwischenspeicherung? Ich muss auf diese Nachrichten nie wieder zugreifen, außer wenn sie zum ersten Mal eintreffen. Wie kann ich das Löschen des Caches erzwingen? Wie kann ich das Auslaufen von Javamail verhindern?

1voto

GreenKiwi Punkte 1007

Ich habe diesen Hinweis im Javamail Forum gefunden Wie kann ich Javamail zwingen, seinen Nachrichten-Cache zu löschen?

Und dann habe ich ein bisschen gegraben. Ich habe zwar keine Möglichkeit gefunden, den "Cache" zu entfernen oder zu verkleinern, aber ich habe herausgefunden, dass der größte Teil des Cache die Kopfzeilen der Nachrichten sind. Es gibt zwei Kopien der Kopfzeilen in IMAPMessage, eine, die es hat, und eine in MIMEMessage, die es auffüllt. Die Schwierigkeit besteht nun darin, diese Informationen zu löschen, da Sie nur Zugriff auf die Informationen in IMAPMessage haben. Die Kopfzeilen in MIMEMessage können nicht gelöscht werden. Außerdem können sie nicht entfernt werden. Hier ist der Code von 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
    }
}
}

Unabhängig davon war ich in der Lage, den vom MessageCache gespeicherten Speicher drastisch zu verringern, indem ich alle diese Werte löschte.

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);
   }
}

Das ist zwar nicht das Schönste, aber es verringert den Speicherbedarf eines Ordners von 40 MB auf 20 MB. Ich werde sehen, ob es noch andere Möglichkeiten gibt, dies zu tun. Idealerweise denke ich, dass ich meine eigene überschriebene IMAPMessage-Klasse erstellen würde, aber das scheint sehr schwierig, in zu loten.

0voto

Moose Morals Punkte 1476

Sie können eine andere Java-Mail-Implementierung ausprobieren, wenn Ihnen die von Sun nicht zusagt. GNU Classpath hat eine (unter http://www.gnu.org/software/classpathx/javamail/javamail.html )

0voto

Miguel Ping Punkte 17786

Nach Angaben der docs geben Sie einen booleschen Wert an, der angibt, dass gelöschte Nachrichten gelöscht werden sollen:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X