Les Fuites de mémoire à l'aide d'Exécuteurs testamentaires.newFixedThreadPool()
Je suis en utilisant Spring3.1 seul env.
(ce problème qui n'est pas nécessaire liée au Printemps. c'est se comporter de la même également autonome env.)
J'ai implémente un auditeur qui reçoit des messages de Sujet. les messages de taux est très élevé (en parlant de 20/30 m/s).
certains messages peuvent prendre plus de temps de traitement puis de l'autre.
L'auditeur travaille avec la même instance qui signifie que si un message en cours de traitement trop long, il frappe nos performances assez bien.
Nous avons pensé faire notre propre piscine d'objets au lieu d'utiliser le même port d'écoute de l'instance, mais ensuite j'ai découvert le Exécuteurs(java.util.de façon concomitante.Les exécuteurs testamentaires).
Donc, pour chaque message reçu sur un autre fil de discussion sera alloué. cela fera en sorte que notre auditeur instance sera libre de traiter les messages en parallèle.
private ExecutorService threadPool = Executors.newFixedThreadPool(100);
@Override
public void onMessage(final Message msg)
{
Runnable t = new Runnable()
{
public void run()
{
onSessionMessage(msg);
log.trace("AbstractSessionBean, received messge");
}
};
threadPool.execute(t);
}
Qui semble résoudre notre problème de performance. mais après le contrôle de l'application avec jconsole nous face maintenant d'énormes fuites de mémoire.
Le segment de l'utilisation de la mémoire en cours a augmenté de manière significative dans le temps.
J'ai donc essayé de "jouer" un peu avec le FixedThreadPool nombre de taille. encore une grande utilisation de la mémoire:
Aucune idée de comment puis-je résoudre ce problème? d'autres idées pour résoudre mon problème de clé?
Après l'exécution de heap dump j'ai deux problème suspects:
grâce,
ray.
Salut Andrew fait, je n'ai pas fait de test de mon programme que loin.. car il semble que le OOM est à venir..
Aussi, si vous êtes déjà profilage: Pouvez-vous faire un heapdump pour voir ce que les objets sont vraiment consommer de l'espace?
ce param pourraient être prises à partir de jconsole? ou Dois-je besoin d'un outil spécifique pour cela?
Vous pouvez utiliser visualvm pour prendre un tas de vidage
OriginalL'auteur rayman | 2012-12-17
Vous devez vous connecter pour publier un commentaire.
Je pense que vous n'avez pas de problème de fuite de mémoire, je ne vois pas ce à partir de votre jconsole graphique au moins. Il n'y a pas de grandes GC collection. Il semble donc de plus en plus objet alloué dans titularisés(ancien) de la génération. Afin de garantir à propos de fuite de mémoire, vous devez Effectuer GC et après que comparer la mémoire allouée. Si vous trouvez une fuite, vous êtes en mesure de faire un tas de vidage avec jmap ou outil visuel(standart JDK outils). Après ce tas de vidage peut être analysé avec MAT. Avant de prendre des tas de vidage il est préférable de procéder à GC pour diminuer tas de vidage de la taille du fichier.
Quelques remarques:
En conséquence votre jconsole capture d'écran, vous avez 1 go de mémoire dédiée. Mais utilisé seulement 30 mo en moyenne. En 3 heures de votre ancien croissance de mémoire jusqu'à 10 mo. Donc JVM décider de ne pas arrêter votre application afin de recueillir de l'ancienne génération tas, à cause de beaucoup de mémoire est gratuit. Initier PerformGC afin de garantir l'absence de fuites de mémoire existe dans votre application. Aussi, si vous diminuez Xmx(il est recommandé de définir cette valeur, le même Serveur d'application), par exemple à 50 mo GC doit être exécuté le plus souvent.
Dans la JConsole de Détails existent partie: GC temps. Il montre comment beaucoup de temps app passé dans le GC. ParNew - est de l'Eden de l'espace de collecte. ConcurrentMarkSweep moyen Permanent de la génération(GC majeur de la collection).
Bizarre chose.. je prends PerformGC via la jconsole. mais rien ne se passe vraiment.. (je suis connecté à partir de la jconsole à distance à l'application vir RMI)
Il serait grand si vous avez mis à jour le post avec une nouvelle capture d'écran de jconsole après l'exécution de la GC.
OriginalL'auteur Taky
Je crois que le problème rencontré est le pool de threads ne pas relâcher ses ressources. Vous devez appeler le pool de threads.shutdown() après vous avez terminé la soumission ou de l'exécution. Cela permettra d'attendre jusqu'à ce que les tâches soient terminées avant la résiliation de threads qui peuvent ensuite être nettoyée.
Officielle de l'api Java site web:
"Un inutilisés ExecutorService devraient être fermées afin de permettre la remise en état de ses ressources."
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdown()
Alternativement, vous pouvez utiliser un newCachedThreadPool() qui Crée un pool de threads qui crée de nouveaux threads en tant que de besoin, mais de réutilisation déjà construits fils quand ils sont disponibles" voir https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
Lorsque j'ai rencontré ce problème, je suis allé avec le newFixedThreadPool() et de l'option d'arrêt.
OriginalL'auteur Enda
Après l'utilisation de ExecutorService, Vous devez arrêter le pool de threads, c'est la même ressource, comme un fichier ou une base de données ou toute autre chose qui nécessite une libération explicite. ExecutorService a des méthodes d'arrêt() et shutdownNow (), qui peut être utilisé dans un bloc finally pour gargabe recueillir.
Si vous oubliez, l'arrêt de la fuite de mémoire se produit, Il est également comme des flux qui ne sont pas normalement fermé par la JVM, car la valeur par défaut Exécuteurs testamentaires ne pas créer des fils de démon.
non, l'exécution d'arriver. Mais les fuites de mémoire peuvent pas être manipulés.
Si vous arrêtez(docs.oracle.com/javase/7/docs/api/java/util/concurrent/...) ExecutorService il n'effectuez jamais de tâche avant les loisirs. L'idée principale du pool de threads est de réutiliser thread pour effectuer différentes tâches de manière asynchrone.
threadPool.execute(t); qui exécute votre fil service. et seulement après l'exécution de l'ARRÊT comme je l'ai montré dans mon code! Afin d'Arrêt() est la méthode qui fait en sorte que toutes vos ressources de ExecutorService sont des Ordures.
Désolé, mais passons en revue javaDoc: Initie un arrêt dans lequel précédemment présenté les tâches sont exécutées, mais pas de nouvelles tâches seront acceptés. Si tous les threads thread sondage va s'arrêter. Comment l'application va traiter les messages des autres?
OriginalL'auteur Harish Raj
Juste une suggestion, mais si vous créez de 30 messages par seconde, et il faut à l'ordinateur (en parallèle) plus de temps pour traiter ces 30 messages que 1 seconde, alors que vous êtes à la file d'attente de tâches va croître de façon incontrôlée. Vous devriez assurez-vous qu'aucune des tâches sont présentées, si la taille de la queue est plus grand qu'un nombre défini et attendre un peu. Chaque objet de Message utilise la mémoire et je pense que ce pourrait être votre problème. Un cachedthreadpool ne résoudra pas ce.
Vous pourriez tout simplement tester cela par l'impression que vous êtes à la taille de file d'attente. Ne sais pas si cela a été résolu....
OriginalL'auteur Martin