J'ai écrit une petite application Java (mon premier!), cela ne fait que quelques choses pour le moment. Actuellement, il gère la classe principale qui lance une classe d'interface graphique (une classe que j'ai écrit qui étend jframe contenant uniquement une JTextarea), une classe qui charge un fichier local via une bufferedInputStream d'environ 40 kb et une classe qui charge une entrée d'une entrée Java Properties Fichier. p>
Tout fonctionne merveilleusement, cependant, je regardais le chef de travail Windows et j'ai remarqué quelque chose qui m'a frappé comme impair. Lorsque je lance l'application, l'utilisation de la RAM saute à environ 40 Mo lorsqu'elle charge le fichier local et tire quelques valeurs à l'affichage dans le JTextarea, qui me semble normale à cause des classes de base JVM, Java, etc. Point, cependant, lorsque l'application a fini de charger le fichier, itherely siège au ralenti, car je ne l'ai pas actuellement faire autre chose. Bien qu'il soit assis oisif, tant que la fenêtre est active, l'utilisation de la mémoire de l'application commence à grimper de 10 à 20kb chaque seconde. Cela me frappe comme impair. Si je clique sur un autre programme pour faire celui-ci la fenêtre inactive, la mémoire augmente encore, mais à un taux beaucoup plus lent (environ 10 ko toutes les 3-5 secondes). P>
Je n'ai pas testé pour voir à quelle distance cela augmenterait, mais cela me frappe comme un comportement très étrange. Est ce comportement de Java normal? Je suppose qu'il est possible que mon code puisse faire des fuites de mémoire, mais je ne sais pas comment. Je me suis assuré de fermer la bufferedInputStream j'utilise et je ne vois pas quoi d'autre causerait cela. P>
Je suis désolé si mon explication n'a pas de sens, mais j'apprécierais tout aperçu et / ou des pointeurs que quiconque peut avoir. P>
mise à jour: p>
Sur suggestion, j'ai essentiellement dépouillé mon application à la classe principale qui appelle simplement la classe d'interface graphique. La classe d'interface graphique ne prolonge que le jframe et définit la taille de la fenêtre, fermer le fonctionnement et les propriétés visibles. Avec ces changements, la mémoire augmente encore à 10-20KB, mais à un taux plus lent. Ceci, en conjugué avec d'autres conseils que j'ai reçus me conduit à croire que ce n'est que Java. Je continuerai à jouer avec elle et à vous laisser tous savoir si je découvre tout autre chose intéressant. P>
5 Réponses :
Félicitations pour votre première application! Maintenant, quelques choses à penser. Premièrement, le gestionnaire de tâches Windows n'est pas une excellente ressource pour comprendre la croissance de votre VM. Au lieu de cela, vous devez surveiller vos statistiques de collecte des ordures dans la console (utilisez le -verbose: GC code> Commandline param). Deuxièmement, si vous êtes préoccupé par les fuites potentielles et la croissance de la machine virtuelle, il existe un tas de grands profileurs qui sont faciles à utiliser et peuvent vous aider à diagnostiquer les problèmes de mémoire. Découvrez ces deux Posts pour certaines options de profileur. P>
@afk, merci! J'ai entendu dire que le responsable de la tâche Windows n'était pas le plus grand des outils de surveillance des applications Java, mais je ne savais pas à quel point l'information était digne de confiance. Je vérifie bien ce que vous avez mentionné.
Félicitations pour votre première application Java! p>
Applications Java exécutées dans une machine virtuelle. La machine virtuelle a été attribuée à une quantité fixe de mémoire par le système d'exploitation, typiquement 512 Mo. Tant que l'application utilise moins de 512 MB, le collecteur des ordures n'entraînera pas et commencez à rechercher des blocs de mémoire "morts". La limite de mémoire JVM peut être modifiée dans la plupart des OSES. Essayez de changer la limite de mémoire à 32 Mo, par exemple. P>
Merci!! Je garderai cela à l'esprit. Je vais essayer de voir à quelle distance cela augmente réellement. Merci pour les suggestions.
Fondamentalement correct, mais pas de JVM que j'ai rencontré va allouer un tas initial que Big (512 Mo) ... À moins que quelque chose ne lui indique spécifiquement via les options de lancement JVM.
est ce comportement de Java normal? P> blockQuote>
Non. P>
Je suppose qu'il est possible que mon code puisse fuite de mémoire p> blockQuote>
C'est certainement la cause. Veuillez afficher votre code source, sinon un diagnostic supplémentaire n'est pas possible. P>
J'ai remarqué que vous utilisez Swing, assurez-vous de lancer votre
jframe code> dans le Dépêche d'événement , à l'aide de la méthode
invoqater (exécutable) code>. p>
Si vous utilisez une sorte de collections, assurez-vous de vous
effacer code> une fois terminé. p>
Puisque vous faites du fichier IO, assurez-vous de fermer toutes les classes impliquées dans les opérations de l'IO après avoir terminé avec eux. P>
Si vous utilisez des auditeurs d'événements, n'oubliez pas de supprimer explicitement les auditeurs d'événements quand ils ne sont plus nécessaires. P>
Une chose que vous pourriez essayer est d'expérimenter. Prenez votre application et supprimez le fichier IO, voyez ce qui se passe. L'utilisation de la mémoire monte-t-elle toujours comme avant? Maintenant, résous votre application à la normale et supprimez la zone de texte - la mémoire monte-t-elle toujours comme avant? Etc, etc. Cela vous aidera à déterminer quelle est la source, et vous pouvez concentrer vos efforts. Très probablement, vous découvrirez ce que vous êtes après en faisant cela. P>
Un autre outil de diagnostic utile consiste à utiliser
system.gc () code> à des moments particuliers à temps, généralement après fort> les blocs de levage lourds du code. Cela indiquera à la JVM d'effectuer une collecte des ordures à ce stade de l'exécution, plutôt que dans une autre fois déterminée par la consommation de mémoire. Cela vous aidera à prendre en compte toutes les fluctuations périodiques de l'utilisation de la mémoire de votre application. P>
omettre qui, vous pouvez toujours utiliser un profileur de mémoire. Si vous utilisez NetBeans IDE, il y en a une intégrée. Pour Eclipse, plusieurs plugins pouvant effectuer un profilage. P>
Oui, c'est Java. Faites avec.
@bguiz Je ne suis pas sûr de comprendre ce que vous entendez par le fil d'expédition de l'événement. Je suis très nouveau à Java et je n'ai pas vu cela mentionné.
@masternosaj: à l'intérieur de votre Public statique Void Médical CODE> PAS INSTANTER votre
JFRAME code> en appelant le constructeur. Au lieu de cela, instanciez-le dans un
Runnable code> et effectuez un
invoqater code> sur le fichier exécutable. Ceci est généralement destiné à la filetage, pas de fuites de mémoire, mais c'est quelque chose que vous devriez faire de toute façon, car c'est à quel point le Sun conçu Swing doit être utilisé.
Essayez de surveiller l'utilisation du tas avec JConsole au lieu du gestionnaire de tâches Windows: P>
Si vous regardez pendant un certain temps, vous obtiendrez probablement un motif "Scietooth" car la mémoire monte au fil du temps, mais a ensuite des déposées tranchantes lorsque le collecteur des ordures s'exécute. Vous pouvez essayer de "suggérer" la collecte des ordures en cliquant sur le bouton So marqué. p>
Lorsque vous faites cela, l'utilisation de la mémoire tombe-t-elle au même niveau minimum ou le minimum global augmente-t-il au cours de plusieurs minutes? Si l'utilisation minimale augmente, vous avez une fuite de mémoire. S'il retourne toujours au même niveau minimum, alors vous allez bien. P> java -dcom.sun.management.jmxremote -jar myapp.jar code> p>
jconsole code> à partir de la ligne de commande et connectez-vous au PID local du processus Java que vous avez démarré dans la dernière étape. LI>
C'était une réponse très perspicace. Je vais essayer!
J'ai essayé le jconsole un essai et c'est un joli utilitaire nifty. Comme je l'ai regardé, l'utilisation de la mémoire de tas a augmenté d'augmentation. Lorsque j'ai invoqué le GC (avec le bouton que vous avez mentionné), l'utilisation de la mémoire a reculé. J'ai essayé cela plusieurs fois et je suis toujours tombé à peu près au même niveau minimum. Merci beaucoup!
Notez que JDK 6 a une utilité encore plus niquante: Jvisalvm. Commencez-le en tapant la commande jvisualvm code> dans une invite de commande.
@Jesper, je vais vérifier cela aussi.
@Jesper merci pour le pointeur - je ne savais pas à ce sujet, mais ça va être utile, car je me batte une question de fuite de mémoire de mienne en ce moment.
C'est normal. Certains contexte Calc peut laisser des objets morts autour, que JVM n'est pas pressé de nettoyer. Finalement, ils seront recueillis à la poubelle lorsque Max Mem est approché. P>
Laissez votre programme courir pendant la nuit et votre machine ne va pas exploser. P>
Félicitations pour votre première application !!! Peut-être que vous pourriez poster du code? Sans code, nous devinons juste. Continuez également à la surveiller pour voir si cela continue vraiment de monter ou de s'arrêter à un moment donné. Postez vos résultats.
@Romain, merci! J'ai pensé à poster mon code, mais honnêtement, j'étais plus intéressé à voir si cela est un comportement de Java normal (je ne le pensais pas, mais tout est possible!). Je vais étudier de plus en plus sur le code si je ne pouvais pas comprendre pourquoi dans quelques jours. Merci!
#masternosaj Il est normal que la mémoire fluctue de rafraîchissements en interne à l'écran et à la collecte des ordures est effectuée. Il n'est pas normal que la mémoire continue de se développer. Si vous êtes un débutant Java, j'ai vu des gens demander des critiques de code des sections de code sur ce site.
@Romain, maintenant cela me fait me sentir mieux, et c'est logique et écrivez-vous rafraîchissant et tel. Merci pour l'aperçu !!