2017-03-06 4 views
0

J'ai une grande boîte aux lettres de millions de messages. Je veux seulement apprendre pour chaque message, qu'il ait ou non un attachement. (Taille non désirée, nom, nombre de pièces jointes, seul le vrai faux suffit). Quand j'utilise ce code et mon moniteur avec un outil de profilage, je vois que le message.getContent() consomme de la mémoire et ne l'efface pas. En traitant des millions de messages, des problèmes de mémoire se produisent. La raison en est que le methot getContent() met en cache des données et les conserve.Java, IMAP, vérifiez si le message a une pièce jointe sans aller chercher

Quelle est une alternative à ce code sans appeler getContent? Ou comment puis-je forcer pour effacer le cache qui est défini par getContent? Comment puis-je appliquer message.writeTo() pour ce cas?

//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

Peut-être que vous pouvez réduire les messages par des messages visibles ou non. Exemple: http://stackoverflow.com/questions/12988799/javamail-check-message-content-gmail-imap –

+0

J'ai besoin de tous à cause de certaines règles métier. Je ne récupère que les en-têtes (sujet, etc.) et ignore le corps, les pièces jointes sans aucun problème de mémoire ou de performance. Mais j'ai seulement besoin d'un attachement ou non. La récupération du corps et des pièces jointes est effectuée lorsque l'utilisateur sélectionne un message ultérieurement. – benchpresser

Répondre

0

Ceci est un problème Java classique. Le schéma général est

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

Chaque foo n'est pas utilisé après sa sortie de la boucle, mais ils restent tous accessibles, de sorte que la machine virtuelle Java se développe très grand. La solution classique n'est pas de conserver des références à des choses dont vous n'aurez pas besoin. Dans votre cas, le tableau message maintient cet accès.

+0

Mon tableau de messages ne contient pas 1 million de messages. Je les manipule en 1000 blocs et récupère 1000 messages, traite, vide le tableau et continue avec le suivant. Quand aucun appel de getContent n'est effectué, aucun problème de mémoire ne se produit. – benchpresser

+1

Le dossier IMAP est/a un tel tableau, donc vous en avez un sauf si vous fermez et rouvrez le dossier. La réouverture d'un gros dossier est cependant très lente. Vous pouvez rendre chaque message plus petit en appelant [invalidateHeaders()] (https://javamail.java.net/nonav/docs/api/com/sun/mail/imap/IMAPMessage.html#invalidateHeaders--), ce qui efface beaucoup plus que sa documentation dit. Peut-être que faire cela et rouvrir tous les 50k messages ou plus est suffisant. – arnt

+0

Merci, je l'ai déjà fait aujourd'hui, et la mémoire est libérée après chaque clôture, les problèmes semblent résolus avec getContent. D'autre part, j'ai essayé d'envoyer une commande customprotocol avec UID FETCH et BODYSTRUCTURE, l'utilisation de la mémoire est très faible par rapport à getContent, il n'y a pas besoin d'ouvrir/fermer le dossier. Les deux méthodes semblent fonctionner. – benchpresser