J'ai rencontré des problèmes avec une faiblesseHashmap.
Considérez cet exemple de code: p> Ce code fonctionne. À l'intérieur des boucles, je crée un objet.Lorsque une GC mineure survient, la taille de la carte est égale à 1 à la 1360ème itération. Tout va bien. P> Maintenant, lorsque je commente cette ligne: P> //anObject = null;
3 Réponses :
Le compilateur juste à temps analyse le code, voit que Plus tard, le GC recueille les cordes car aucune forte références ne leur reste. P>
Si vous avez utilisé anoObject code> et
autreObject code> ne sont pas utilisés après la boucle et les supprime de la table de variable locale ou des ensembles les
NULL code>, tandis que la boucle est toujours en marche. Ceci s'appelle la compilation OSR. P>
anObject code> après la boucle, vous obtiendriez toujours un
OutofMemoryError code>. P>
Je pense que vous avez exactement raison - mais n'est-ce pas une optimisation de JIT potentiellement brisant? Si anoObject code> a un finaliseur et c'est GC'D avant que la référence ne disparaisse que le finaliseur s'exécutera potentiellement avant que cela soit censé.
Que pouvait-il casser? Lorsque le finaliseur est exécuté, la forte référence n'existe plus.
Il pourrait casser dans le sens où il pourrait exécuter un finisseur plus tôt que ce que vous n'attendez pas; avant que la référence difficile ne soit effectivement sortie de portée.
Bon point. Je suppose que la leçon est que vous ne pouvez pas compter sur quand (ou si i>) les finaliseurs sont exécutés. Cela peut être plus tôt que vous n'attendez pas seulement plus tard.
Bit de creusement révèle que cela est explicitement couvert dans les JLS, section 12.6.1:
L'optimisation des transformations d'un programme peut être conçu de façon à réduire le nombre d'objets qui sont accessibles à moins de celles qui seraient considérés comme accessibles naïvement être. Par exemple, un générateur de compilateur ou un code peut choisir de définir une variable ou un paramètre qui ne sont plus utilisées null pour que le stockage pour un tel objet potentiellement récupérables plus tôt. Strong> p> Blockquote>
(Bolding est une addition.) P>
http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.6.1 p>
donc, en essence, le JIT est autorisé à supprimer les références fortes à chaque fois qu'il veut si elle peut travailler qu'ils ne seront jamais utilisés à nouveau -. qui est exactement ce qui se passe ici p>
Ceci est une grande question cependant et fait pour un jeu de réflexion qui peut facilement montrer simplement parce qu'un objet semble avoir une référence forte portée, ne signifie pas nécessairement qu'il n'a pas été déchets collectés. ! À la suite de cela, il signifie que vous pouvez explicitement rien de garantie quand un finaliseur fonctionnera, cela peut même être dans le cas où il semble que l'objet est toujours portée p>
Par exemple: p >
List<byte[]> list = new ArrayList<byte[]>(); Object thing = new Object() { protected void finalize() { System.out.println("here"); } }; WeakReference<Object> ref = new WeakReference<Object>(thing); while(ref.get()!=null) { list.add(new byte[10000]); } System.out.println("bam");
Juste pour ajouter une petite chose à l'excellente réponse de Joni Salonen em> et berry120 em>. Il peut être montré que le JIT est en réalité responsable de la "variable supprimer" la désactivation simplement avec Si nous voulons savoir ce qui se passe sous les hottes, l'option La dernière compilation (avec le drapeau @) est une compilation OSR (sur le remplacement de la pile) ( Vérifiez https://gist.github.com/rednaxelafx/1165804#osr pour plus d'informations des détails). En mots simples, il permet à la machine virtuelle de remplacer une méthode lorsqu'elle est en cours d'exécution et qu'elle est utilisée pour améliorer les performances des méthodes Java bloquées dans des boucles. Je suppose que, après la déclenchement de cette compilation, le JIT supprime les variables qui ne sont plus utilisées. P> P> -djava.compiler = Aucun code>. Une fois que vous l'éteignez, vous obtenez l'Oome.
xx: + impressionnaison code> montre l'activité JIT. Utilisant avec le code de la question La sortie que nous obtenons est la suivante: p>
Je pense que votre test n'est pas correct. Si vous changez
tandis que (map.size () == 2) { code> à
tandis que (map.size ()> 0) { code>, les deux tests finiront tous les deux jusqu'à la La carte est vide, peu importe votre commentaire
anoObject = null code> ou non. BTW, j'ai déjà essayé.
Imprimer
anObject code> et
autreObject code> à la fin. Le compilateur voit que vous ne les utilisez plus et que vous pouvez les supprimer plus tôt.