cordes sont problématiques
Fondamentalement en Java, String
références (choses qui utilisent char[]
dans les coulisses) dominera la plupart entreprises applications mémoire sage. La manière dont ils sont créés détermine la quantité de mémoire qu'ils consomment dans la JVM. Tout simplement parce qu'ils sont si fondamentaux pour la plupart des applications professionnelles en tant que type de données, et qu'ils sont également les plus gourmands en mémoire. Ce n'est pas seulement une chose Java, String
les types de données occupent beaucoup de mémoire dans à peu près toutes les bibliothèques de langue et d'exécution, car au moins ils sont juste des tableaux de 1 octet par caractère ou pire (Unicode) ils sont des tableaux de plusieurs octets par caractère.
Une fois lors du profilage utilisation du processeur sur une application web qui avait aussi une dépendance JDBC Oracle j'ai découvert que StringBuffer.append()
dominé les cycles CPU par plusieurs ordres de grandeur par rapport à tous les autres appels de méthode combinée, beaucoup moins tout autre appel de méthode unique. Le pilote JDBC a fait beaucoup, beaucoup de manipulation String
, sorte de compromis de l'utilisation de PreparedStatements
pour tout.
Qu'est-ce que vous êtes préoccupé par vous ne pouvez pas contrôler, non pas directement de toute façon
Ce que vous devez vous concentrer sur ce qui est dans votre contrôle, ce qui fait que vous ne tenez pas à des références plus que vous devez, et que vous ne dupliquez pas les choses inutilement. Les routines de récupération de place Java sont hautement optimisées, et si vous apprenez comment leurs algorithmes fonctionnent, vous pouvez vous assurer que votre programme se comporte de manière optimale pour que ces algorithmes fonctionnent.
Java Heap mémoire est pas comme mémoire gérée manuellement dans d'autres langues, ces règles ne sont pas applicables
Qu'est-ce que sont considérés comme des fuites de mémoire dans d'autres langues ne sont pas la même chose/cause racine en Java avec son système de collecte des ordures.
La mémoire Java n'est probablement pas consommée par un seul objet uber qui fuit (référence pendante dans d'autres environnements).
Il est beaucoup plus probable des allocations plus petites en raison de StringBuffer
/objets StringBuilder
pas de taille appropriée, sur les premières instantantations et ayant à croître automatiquement les tableaux char[]
pour tenir append()
ultérieures appels.
Ces objets intermédiaires peuvent être conservés plus longtemps que prévu par le garbage collector en raison de la portée dans laquelle ils se trouvent et de beaucoup d'autres choses qui peuvent varier au moment de l'exécution.
Exemple: le collecteur d'ordures peut décider qu'il ya des candidats, mais parce qu'il estime qu'il y a beaucoup de mémoire encore être fait qu'il pourrait être temps trop cher sage de les débusquer à ce moment, et il attendra jusqu'à ce que la pression de la mémoire augmente.
Le garbage collector est vraiment bon maintenant, mais ce n'est pas magique, si vous faites des choses dégénérées, cela ne fonctionnera pas de façon optimale. Il y a beaucoup de documentation sur Internet à propos des paramètres de garbage collector pour toutes les versions des JVM.
Ces objets non référencés n'ont peut-être pas atteint l'heure à laquelle le ramasse-miettes pense qu'ils en ont besoin pour être effacés de la mémoire, ou il pourrait y avoir des références à un autre objet (List
) par exemple que vous ne réalisez pas encore de points sur cet objet. C'est ce que l'on appelle le plus souvent une fuite en Java, qui est une fuite de référence plus spécifiquement.
Exemple: Si vous savez que vous devez construire un 4K String
en utilisant un StringBuilder
créer avec new StringBuilder(4096);
pas la valeur par défaut, ce qui est comme 32 et immédiatement commencer à créer des déchets qui peuvent représenter plusieurs fois ce que vous pensez que l'objet devrait être taille sage.
Vous pouvez découvrir combien de types d'objets sont instanciés avec VisualVM, cela vous dira ce que vous devez savoir. Il n'y aura pas un seul gros clignotant qui pointe vers une seule instance d'une seule classe qui dit: «C'est le grand consommateur de mémoire!», À moins qu'il n'y ait qu'une seule instance de certains char[]
que vous lisez un fichier massif dans, et ce n'est pas possible non plus, car beaucoup d'autres classes utilisent char[]
en interne; et alors vous le saviez déjà.
Je ne vois aucune mention de OutOfMemoryError
Vous n'avez probablement pas un problème dans votre code, le système de collecte des ordures pourrait bien ne pas être de se mettre sous une pression suffisante pour lancer et objets désaffecter que vous pense il devrait être de nettoyage. Quel vous pensez que est probablement pas un problème, non à moins que votre programme plante avec OutOfMemoryError
.Ce n'est pas C, C++, Objective-C, ou tout autre langage de gestion de mémoire manuelle/runtime. Vous ne pouvez pas décider ce qui est en mémoire ou non au niveau de détail auquel vous vous attendez.
J'utilise un profileur qui me montre également où les objets sont alloués. Je ne sais pas si VisualVM peut le faire, mais c'est très utile. Celui que j'utilise est YourKit, mais ce n'est pas gratuit (mais vous pouvez obtenir une licence eval) –
@PeterLawrey J'ai effectivement lu une réponse que vous avez écrite il y a quelque temps où vous avez mentionné que yourkit était votre premier choix, je l'ai cherché (car votre conseil est toujours génial) mais oui c'est un peu cher et je suis en train d'apprendre. –
sans utiliser quelque chose qui instrumente votre code, aucun analyseur ne sera capable de montrer quelle instance == ce que vous appelez une référence dans votre source. –