Question

La machine virtuelle Java déplace-t-elle jamais des objets en mémoire et, dans l'affirmative, comment gère-t-elle la mise à jour des références à l'objet déplacé?

Je demande parce que j'explore l'idée de stocker des objets de manière distribuée (c.-à-d. sur plusieurs serveurs), mais j'ai besoin de pouvoir déplacer des objets entre serveurs pour des raisons d'efficacité. Les objets doivent pouvoir contenir des pointeurs les uns sur les autres, même sur des objets situés sur des serveurs distants. J'essaie de trouver le meilleur moyen de mettre à jour les références aux objets déplacés.

Mes deux idées à ce jour sont les suivantes:

  1. Conservez une indirection de référence quelque part qui ne bouge pas pendant la durée de vie de l'objet, que nous mettons à jour si l'objet se déplace. Mais comment ces indirections sont-ils gérés?
  2. Conservez une liste de références inverses avec chaque objet afin que nous sachions ce qui doit être mis à jour si l'objet est déplacé. Bien sûr, cela crée une surcharge de performances.

Je souhaiterais recevoir des commentaires sur ces approches et des suggestions d’approches alternatives.

Était-ce utile?

La solution

En référence au commentaire ci-dessus sur la marche du tas.

Différents GC font les choses différemment.

Généralement, en copiant les collectionneurs quand ils marchent dans le tas, ils ne marchent pas avec tous les objets du tas. Plutôt, ils marchent les objets LIVE dans le tas. L’implication est que si elle est accessible à partir de la & racine; racine " objet, l'objet est en direct.

Donc, à ce stade, il doit quand même toucher tous les objets vivants, car il les copie de l’ancien tas au nouveau tas. Une fois la copie des objets réels terminée, il ne reste plus dans l'ancien segment ni des objets déjà copiés, ni des déchets. À ce stade, l’ancien tas peut être complètement jeté.

Ce type de collecteur présente deux avantages principaux: il compacte le tas pendant la phase de copie et ne copie que des objets vivants. Ceci est important pour de nombreux systèmes car avec ce type de collecteur, l’allocation d’objets est extrêmement économique, ne menant qu’à incrémenter un pointeur de tas. Lorsque la GC se produit, aucun des "morts" ne les objets sont copiés, ils ne ralentissent donc pas le collecteur. Dans les systèmes dynamiques, il s'avère également qu'il y a beaucoup plus de déchets temporaires que de déchets de longue date.

De plus, en parcourant le graphique d'objet réel, vous pouvez voir comment le GC peut "savoir". à propos de chaque objet, et en garder trace pour tout ajustement d’adresse effectué pendant la copie.

Ce n’est pas le forum pour parler en profondeur de la mécanique GC, c’est un problème non trivial, mais c’est la base du fonctionnement d’un collecteur de copie.

Un GC de copie générationnelle mettra "ancien". des objets en différents tas, et ceux-ci finissent par être ramassés moins souvent que "plus récent" des tas. La théorie est que les objets de longue durée sont promus auprès des générations précédentes et sont de moins en moins collectés, ce qui améliore les performances globales du GC.

Autres conseils

(Pratiquement) Tout système récupéré doit déplacer les objets en mémoire pour les empaqueter de manière plus dense et éviter les problèmes de fragmentation.

Ce que vous regardez est un sujet très vaste et complexe. Je vous conseillerais de lire les API de style d'objet distant existantes: .NET remoting et des technologies plus anciennes telles que CORBA

Toute solution de suivi des références sera compliquée par la gestion de tous les modes de défaillance existant dans les systèmes distribués. La machine virtuelle Java n'a pas à craindre de ne pas voir tout à coup qu'elle ne peut pas voir la moitié de son tas, car un commutateur de réseau est tombé en panne.

Lorsque vous explorez la conception, je pense que cela dépendra en grande partie de la manière dont vous souhaitez gérer différents cas d'échec.

Réponse aux commentaires:

Votre question concerne le stockage d'objets de manière distribuée, ce qui correspond exactement à ce que sont les adresses .NET à distance et les adresses CORBA. Certes, aucune technologie ne prend en charge la migration de ces objets (autant que je sache). Mais ils abordent tous les deux de manière approfondie les concepts d’identité d’objet qui constituent une partie essentielle de tout système d’objet distribué: comment les différentes parties du système savent-elles de quels objets elles parlent?

Je ne connais pas très bien les détails du récupérateur de déchets Java. Je suis certain que les récupérateurs de déchets Java et .NET ont beaucoup de complexité pour obtenir des performances optimales avec un impact minimal sur l'application.

Cependant, l'idée de base pour la récupération de place est la suivante:

  • La machine virtuelle arrête l'exécution de code managé par tous les threads
  • Il effectue une analyse d'accessibilité à partir de l'ensemble des 'racines' connues: variables statiques, variables locales sur tous les threads. Pour chaque objet trouvé, il suit toutes les références qu'il contient.
  • Tout objet non identifié par l'analyse d'accessibilité est inutilisable.
  • Les objets encore vivants peuvent ensuite être déplacés vers le bas dans la mémoire pour les compresser de manière dense. Cela signifie que toute référence à ces objets doit également être mise à jour avec la nouvelle adresse. En contrôlant le moment où une collecte de données peut se produire, la machine virtuelle est en mesure de garantir qu’aucune référence d’objet «en vol» (c’est-à-dire conservée dans un registre de machine) ne poserait problème.
  • Une fois le processus terminé, la machine virtuelle redémarre l'exécution des threads.

En guise de raffinement de ce processus, la machine virtuelle peut effectuer une récupération de place générationnelle, dans laquelle des tas distincts sont gérés en fonction de "l'âge" d'un objet. Les objets commencent dans le tas 0 et s'ils survivent à plusieurs GC, puis migrent vers le tas 1 et éventuellement vers le tas 2 (et ainsi de suite - .NET ne prend en charge que 3 générations). L'avantage de ceci est que le GC peut exécuter très fréquemment des collections de tas 0 sans avoir à s'inquiéter de faire le travail pour prouver que les objets ayant vécu longtemps (qui se sont retrouvés dans le tas 2) sont toujours vivants (ce qu'ils sont presque certainement). .

Il existe d'autres améliorations permettant de prendre en charge la récupération de place simultanée, ainsi que des détails sur les threads exécutant du code non managé lors de la planification du catalogue global, ce qui ajoute beaucoup plus de complexité à ce domaine.

Je serais curieux d'en savoir plus sur vos besoins. Comme le suggère une autre réponse, Terracotta peut être exactement ce que vous recherchez.

Il existe cependant une différence subtile entre ce que Terracotta fournit et ce que vous demandez, donc ma demande.

La différence est que, en ce qui vous concerne, Terracotta ne fournit pas "distant". des références à des objets - en fait l’ensemble "quotient à distance" La notion de RMI, JMS, etc. est totalement absente lors de l’utilisation de Terracotta.

Plutôt dans Terracotta, tous les objets résident dans un grand tas virtuel. Les threads, qu'ils se trouvent sur les nœuds 1, 2, 3, 4, etc. ont tous accès à tous les objets du segment de mémoire virtuel.

Il n’existe pas de programmation spéciale à apprendre, ni d’API spéciales, d’objets dans les objets "virtuels". tas ont exactement le même comportement que les objets du tas local.

En résumé, Terracotta fournit un modèle de programmation pour plusieurs machines virtuelles qui fonctionne exactement de la même manière que le modèle de programmation d’une seule machine virtuelle. Les threads dans des nœuds distincts se comportent simplement comme des threads dans un nœud unique: mutations d'objet, synchronisées, attente, notification, comportement identique pour tous les nœuds et entre threads: il n'y a pas de différence.

En outre, contrairement aux solutions proposées, les références aux objets sont conservées sur tous les nœuds. Vous pouvez donc utiliser ==. Tout cela fait partie de la maintenance du modèle de mémoire Java sur le cluster, ce qui est la condition fondamentale pour effectuer des opérations "régulières". Java (par exemple, les POJO, synchronisé, attente / notification) fonctionne (rien de cela ne fonctionne si vous ne conservez / ne pouvez pas préserver l'identité de l'objet sur le cluster).

La question vous revient donc de préciser davantage vos besoins - à quelle fin avez-vous besoin de " télécommande " pointeurs?

Le mot clé que vous recherchez est "compactage du ramasse-miettes". Les machines virtuelles sont autorisées à en utiliser un, ce qui signifie que les objets peuvent être déplacés. Consultez le manuel de votre machine virtuelle Java pour savoir si le vôtre l’est et si des options de ligne de commande l’affectent.

Le moyen le plus simple d’expliquer la compaction consiste à supposer que le ramasse-miettes fige tous les threads, déplace l’objet, recherche dans le tas et la pile toutes les références à cet objet et les met à jour avec la nouvelle adresse. En réalité, c'est plus complexe que cela, car pour des raisons de performances, vous ne souhaitez pas effectuer un balayage complet avec des threads bloqués. Par conséquent, un récupérateur de mémoire incrémentiel se préparera à la compression dès que possible.

Si vous êtes intéressé par les références indirectes, vous pouvez commencer par rechercher des références faibles et souples en Java, ainsi que les références distantes utilisées par divers systèmes RPC.

On dirait que vous recherchez un cache distribué, un peu comme de la terre cuite ou le cache java objece d’Oracle (anciennement Tangersol).

Si vous êtes prêt à aller aussi loin, vous pouvez consulter les documents d'architecture de JBoss Cache et utiliser une partie de son code source comme référence.

Ce n'est pas exactement ce que vous avez décrit, mais cela fonctionne de manière très similaire.

Voici le lien.

http://www.jboss.org/jbosscache/

J'espère que cela vous aidera.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top