2010-01-18 5 views
1

Le morceau de code suivant observé sous JConsole montre une augmentation constante de la taille du tas. Le tas atteint un maximum de 25 Mo, puis le GC fonctionne et diminue la taille du tas à près de 3 Mo. Est-ce le comportement attendu ? Je suis très surpris!Allocation de mémoire Java non demandée

public class Dummy { 
    public static void main(String[] args) { 
     System.out.println("start"); 
     while(true){ 
      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

J'utilise Snow Leopard.

Répondre

8

La communication avec jconsole provoque l'attribution d'objets. Je crois que ce que vous voyez ici est un artefact de votre méthode de mesure. Il peut également y avoir une légère allocation par HotSpot lors de la compilation du code. Si vous êtes inquiet, utilisez un profileur pour voir ce qui est alloué (encore une fois, faites attention aux allocations par l'interface du profileur).

Le comportement normal du GC est d'éviter de fonctionner inutilement. Vous verrez partout sur le web des graphiques en dents de scie de l'utilisation de la mémoire. Il y a un compromis ici entre le cache et la convivialité de l'échange et éviter le travail. Le serveur HotSpot est également plus agressif quant à l'utilisation de la mémoire que le client HotSpot.

+0

+1 - Je suis sûr que c'est la réponse. Il est très improbable que la classe ci-dessus consomme une quantité notable d'espace de tas dans la boucle.En fait, je m'attendrais à des allocations nulles dans la boucle. Même si la JVM alloue (disons) 100 octets pour chaque appel de sommeil, il va falloir un temps TRÈS LONG pour atteindre 25Mb. –

3

Oui, c'est normal. Vous ne créez pas explicitement d'objets, mais vous appelez des méthodes qui créent probablement des objets temporaires dans le cadre de leur implémentation. Ces objets temporaires s'accumulent jusqu'à ce qu'il soit temps pour une course GC de les nettoyer.

4

Oui, cela devrait être le comportement attendu. Bien que vous ne fassiez rien d'spécifique pour allouer des objets, l'implémentation de sleep pourrait être, et même si ce n'est pas le cas, il y a d'autres threads en cours d'exécution dans la JVM, cela pourrait bien l'être.

+0

Oui, les autres threads en cours sont les plus probables. Thread.sleep appelle simplement une méthode native. – Pool

2

Les fichiers de classe ressemblent à ça, le code passe de 8 à 14, et java.lang.Thread.sleep() est natif. Par conséquent, il n'y a aucune raison de créer de MB d'objets

public static void main(java.lang.String[] args); 
    0 getstatic java.lang.System.out : java.io.PrintStream [16] 
    3 ldc <String "start"> [22] 
    5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [24] 
    8 ldc2_w <Long 5000> [30] 
    11 invokestatic java.lang.Thread.sleep(long) : void [32] 
    14 goto 8 
    17 astore_1 [e] 
    18 aload_1 [e] 
    19 invokevirtual java.lang.InterruptedException.printStackTrace() : void [38] 
    22 goto 8 

Je crains que ce que vous voyez est de JProfiler lui-même (je ne sais pas comment vous attaché à votre application de test factice) ou d'autres choses en cours d'exécution dans ce vm. Pour savoir quels objets ont été créés, vous devez effectuer un vidage de tas si JProfiler n'affiche pas ces informations.

'

+0

N'aide pas. Le code natif peut très heureusement allouer des objets de tas Java. –

+1

Peut-être qu'ils ont mis en sommeil comme ça: new Pillow(); ;-) – stacker

1

Il y a clairement deux théories quant à la cause, et il est impossible de les distinguer fondée sur un raisonnement empirique. Puis-je suggérer une expérience simple.

  1. changer le programme de dormir pendant 1 milliseconde au lieu de 5000. (Le nombre réel n'a pas d'importance ... est de rendre l'allocation de mémoire émis l'hypothèse arrive aussi vite que possible. Vous pouvez également essayer 0 millisecondes , mais le comportement de sommeil peut bien être différent ...)

  2. Exécutez le programme en utilisant l'approche actuelle; par exemple. avec jconsole.

  3. Exécutez le programme sans jconsole, etc, mais avec l'option "-verbose: gc" pour que vous puissiez voir quand le GC fonctionne.

Je pense que vous serez à court de patience en attendant le GC de fonctionner dans le dernier cas ... même appeler sleep aussi vite que possible.

+0

Ou pointez un profileur. –

+0

Un profileur pourrait entraîner des allocations inexpliquées ... bien que cela soit peu probable. –