J'ai utilisé des tailles de tas de plus de 60 Go sur deux applications différentes sous Linux et Solaris respectivement, en utilisant des versions 64 bits (évidemment) de la JVM Sun 1.6.
Je n'ai jamais rencontré de problèmes de garbage collection avec l'application basée sur Linux, sauf lorsque je me rapprochais de la taille limite du tas. Pour éviter les problèmes de "thrashing" inhérents à ce scénario (trop de temps passé à faire du garbage collection), j'ai simplement optimisé l'utilisation de la mémoire dans le programme de façon à ce que les pics d'utilisation soient environ 5-10% en dessous de la taille limite du tas de 64 Go.
Cependant, avec une autre application fonctionnant sous Solaris, j'ai rencontré d'importants problèmes de collecte de déchets, ce qui m'a obligé à procéder à de nombreux ajustements. Cela consistait principalement en trois étapes :
-
Permet/impose l'utilisation du ramasseur de déchets parallèle via les options JVM -XX:+UseParallelGC -XX:+UseParallelOldGC, ainsi que le contrôle du nombre de threads GC utilisés via l'option -XX:ParallelGCThreads. Voir " Optimisation de la collecte d'ordures de la machine virtuelle HotSpot de Java SE 6 "pour plus de détails.
-
La mise en place extensive et apparemment ridicule de variables locales à "null" après qu'elles ne soient plus nécessaires. La plupart d'entre elles étaient des variables qui auraient dû faire l'objet d'un ramassage après être sorties de leur périmètre, et il ne s'agissait pas de fuites de mémoire puisque les références n'étaient pas copiées. Cependant, cette stratégie de "main tendue" pour faciliter la collecte des déchets était inexplicablement nécessaire pour une raison quelconque pour cette application sous la plate-forme Solaris en question.
-
Utilisation sélective de l'appel de la méthode System.gc() dans des sections de code clés après de longues périodes d'allocation temporaire d'objets. Je suis conscient des mises en garde standard contre l'utilisation de ces appels, et de l'argument selon lequel ils devraient normalement être inutiles, mais j'ai trouvé qu'ils étaient essentiels pour maîtriser le ramassage des ordures lors de l'exécution de cette application gourmande en mémoire.
Les trois étapes ci-dessus ont permis de contenir l'application et de la faire fonctionner de manière productive à environ 60 Go d'utilisation du tas, au lieu de la faire croître de manière incontrôlée jusqu'à la limite de 128 Go qui était en place. Le collecteur d'ordures parallèle, en particulier, a été très utile car les cycles de collecte d'ordures majeurs sont coûteux lorsqu'il y a beaucoup d'objets, c'est-à-dire que le temps requis pour une collecte d'ordures majeure est fonction du nombre d'objets dans le tas.
Je ne peux pas faire de commentaires sur d'autres problèmes spécifiques à la plate-forme à cette échelle, et je n'ai pas utilisé de JVM autres que Sun (Oracle).