9
votes

Pourquoi le JVM n'a-t-il pas détruit une ressource dès que son compte de référence atteint 0?

Je me suis toujours demandé pourquoi le collecteur des ordures de Java s'active chaque fois que cela ressemble à cela plutôt que de faire:

if(obj.refCount == 0)
{
   delete  obj;
}


0 commentaires

5 Réponses :


2
votes

Parce que cela ne fonctionne pas strictement basé sur le comptage de référence.

envisager des références circulaires qui ne sont plus accessibles de la "racine" de l'application.

Par exemple:

app a une référence à quelque_screen

quelque_screen a une référence à quelque_child

quelque_child a une référence à quelque_screen

MAINTENANT, APP DROPS C'est une référence à quelque_screen .

Dans ce cas, quelque_screen a toujours une référence à quelque_child et one_child a toujours une référence à one_screen - Donc, dans ce cas, votre exemple ne fonctionne pas.

Maintenant, d'autres (Apple avec ARC, Microsoft avec Com, beaucoup d'autres) ont des solutions pour cela et travaillent plus de la même manière que vous le décrivez.

avec arc, vous devez annoter vos références avec des mots-clés tels que fort et faible pour laisser Arc savoir comment faire face à ces références (et éviter les références circulaires) ... (Ne lisez pas trop loin dans mon exemple spécifique avec ARC, car ARC gère ces choses à l'avance pendant le processus de compilation et ne nécessite pas de temps d'exécution spécifique en soi) afin qu'il puisse certainement être fait de la même manière que vous décrivez Cela, mais ce n'est tout simplement pas fonctionnel avec certaines des caractéristiques de Java. Je crois aussi que COM travaille plus de la même manière que vous décrivez ... mais encore une fois, cela n'est pas exempt de considération de considération sur la partie du développeur.

En fait, aucun système de comptage de référence "simple" ne serait jamais exécutif sans une certaine réflexion par le développeur d'applications (pour éviter les références circulaires, etc.)


0 commentaires

0
votes

Parce que le collecteur des ordures dans les JVM modernes ne suit plus les références comptent. Cet algorithme est utilisé pour enseigner la manière dont GC fonctionne, mais c'était à la fois consommant des ressources et des dépendances cycliques (par exemple).


1 commentaires

Je ne pense pas que tout JVM traditionnel ait jamais utilisé le comptage de référence.



4
votes

Comptage de référence comporte les limitations suivantes:

  • Il est très mauvais pour les performances multithreading (fondamentalement, chaque affectation d'une référence d'objet doit être protégée).
  • Vous ne pouvez pas vous libérer des cycles automatiquement

0 commentaires

19
votes

Chaque JVM est différent, mais le hotspot jvm ne dépend pas principalement de compter en référence comme moyen de collecte des ordures. Le comptage de référence présente l'avantage d'être simple à mettre en œuvre, mais il est intrinsèquement sujet à une erreur. En particulier, si vous avez un cycle de référence (un ensemble d'objets qui se réfèrent tous dans un cycle), le comptage de référence ne récupérera pas correctement ces objets car ils ont tous des comptes de référence non nul. Cela vous oblige à utiliser un collecteur auxiliaire des ordures de temps en temps, qui a tendance à être plus lent (Mozilla Firefox avait ce problème exacte, et leur solution était d'ajouter un collecteur à ordures au prix de la lisibilité de nombreuses personnes). C'est pourquoi, par exemple, des langues telles que C ++ ont tendance à avoir une combinaison de partagée_ptr S qui utilise le comptage de référence et faibles_ptr s qui n'utilise pas les cycles de référence.

En outre, associer un compte de référence avec chaque objet rend le coût d'attribution d'une référence supérieure à la normale, en raison de la comptabilité supplémentaire impliquée de l'ajustement du nombre de références (qui ne s'aggrave que dans la présence de multithreading). En outre, l'utilisation de la comptage de référence empêche l'utilisation de certains types d'allocateurs de mémoire, ce qui peut être un problème. Il a également tendance à entraîner la fragmentation des tas dans sa forme naïve, car les objets sont dispersés à travers la mémoire plutôt que sur des délais de répartition réduites étroitement remplis et causant une mauvaise localité.

Le hotspot jvm utilise une variété de techniques différentes pour la collecte des ordures, mais son collecteur principal principal est appelé collecteur d'arrêt et de copie. Ce collecteur fonctionne en attribuant des objets contiguës dans la mémoire à côté les uns des autres et permet une allocation extrêmement rapide (une ou deux instructions d'assemblage) de nouveaux objets. Lorsque l'espace s'épuise, tous les nouveaux objets sont gc »simultanément, ce qui tue généralement la plupart des nouveaux objets construits. En conséquence, la GC est beaucoup plus rapide qu'une implémentation de comptage de référence typique et finit par avoir une meilleure localité et une meilleure performance.

Pour une comparaison des techniques de la collecte de déchets, ainsi qu'un aperçu rapide de la manière dont le gc de hotspot fonctionne, vous voudrez peut-être vérifier Ces diapositives de cours d'un cours de compilateurs que j'ai enseigné l'été dernier. Vous voudrez peut-être aussi regarder Le papier blanc de collection à ordures hotspot qui passe beaucoup plus en détail sur la manière dont le collecteur des ordures fonctionne, y compris des moyens de réglage du collecteur sur une base d'application par application.

J'espère que cela vous aide!


2 commentaires

+1 Il convient également de mentionner que les bosses de comptoirs atomiques pour des programmes multithreads sont encore plus chères.


Une discussion est incomplète sans mentionner la pause GC.