2017-03-06 2 views
0

Ich habe ein großes Postfach von Millionen von Nachrichten. Ich möchte nur für jede Messe lernen, ob es eine Anhaftung hat oder nicht. (Nicht interessiert Größe, Name, Anzahl der Anhänge, nur wahr falsch ist genug). Wenn ich diesen Code verwende und mit einem Profiler-Tool überwache, sehe ich, dass message.getContent() Speicher verbraucht und nicht löscht. Da es sich um Millionen von Nachrichten handelt, treten Probleme mit dem Arbeitsspeicher auf. Der Grund dafür ist, dass der getContent() -Methot einige Daten zwischenspeichert und speichert.Java, IMAP, prüfen, ob die Nachricht Anhang hat, ohne zu holen

Was ist eine Alternative zu diesem Code ohne Aufruf getContent? Oder wie kann ich erzwingen, den Cache zu löschen, der von getContent gesetzt wird? Wie kann ich message.writeTo() für diesen Fall anwenden?

//processing million message instances in a loop i=1, 1000000 

Multipart multiPart = (Multipart) message[i].getContent(); 
for (int i = 0; i < multiPart.getCount(); i++) { 
    MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(i); 
    if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) { 
        // yes, it has an attachment 
        return true; 
    } 
} 
return false; 
+0

Vielleicht können Sie Nachrichten durch gesehene oder ungesehene Nachrichten reduzieren. Beispiel: http://stackoverflow.com/questions/12988799/javamail-check-message-content-gmail-imap –

+0

Ich brauche alle von ihnen wegen einiger Geschäftsregeln. Ich hole nur Header (Betreff, von etc) und Ignoriere Körper, Anhänge ohne Speicher oder Leistungsproblem. Aber ich brauche nur wenn ich Anhang habe oder nicht. Das Abrufen von Text und Anhängen erfolgt, wenn der Benutzer später eine Nachricht auswählt. – benchpresser

Antwort

0

Dies ist ein klassisches Java-Problem. Das allgemeine Muster ist

while(true) { 
    Something foo = new Something(); 
    processSomehow(foo); 
    someCollection.add(foo); 
} 
// at this point, all of the created objects remain reachable 

Jede foo nicht verwendet wird, nachdem es die Schleife verlässt, aber sie alle erreichbar bleiben, so dass die JVM wächst sehr groß. Die klassische Lösung ist nicht, Referenzen auf Dinge zu behalten, die Sie nicht benötigen. In Ihrem Fall hält das message Array dies erreichbar.

+0

Mein Nachrichtenarray ist nicht 1 Million Nachrichten lang. Ich handle mit ihnen in 1000 Blöcken und hole 1000 Nachrichten, verarbeite, leere das Array und fahre mit dem nächsten fort. Wenn kein Aufruf von getContent erfolgt, treten keine Speicherprobleme auf. – benchpresser

+1

Der IMAPFolder ist/hat ein solches Array, also haben Sie eines, wenn Sie den Ordner nicht schließen und erneut öffnen. Das erneute Öffnen eines großen Ordners ist jedoch sehr langsam. Sie können jede Nachricht verkleinern, indem Sie [invalidateHeaders()] (https://javamail.java.net/nonav/docs/api/com/sun/mail/imap/IMAPMessage.html#invalidateHeaders---) aufrufen, wodurch vieles gelöscht wird mehr als seine Dokumentation sagt. Vielleicht reicht es aus, alle 50.000 Nachrichten erneut zu öffnen. – arnt

+0

Danke, ich habe das heute schon gemacht, und der Speicher wird nach jedem Schließen freigegeben, das Problem scheint mit getContent gelöst zu sein. Auf der anderen Seite, habe ich versucht, customprotocol Befehl mit UID FETCH und BODYSTRUCTURE, die Speicherauslastung ist sehr klein im Vergleich zu getContent, gibt es keine Notwendigkeit, Ordner zu öffnen/schließen. Beide Methoden scheinen zu funktionieren. – benchpresser

Verwandte Themen