Je parcourais de vieux livres et ai trouvé une copie de "Practical Java" de Peter Hagger. Dans la section Performances, il est recommandé de définir les références d'objet à null
lorsqu'elles ne sont plus nécessaires.
En Java, la définition de références d'objet sur null
améliore-t-elle les performances ou l'efficacité de la récupération de place Si oui, dans quels cas s'agit-il d'un problème? Classes de conteneurs? Composition d'objet? Classes internes anonymes?
Je vois cela assez souvent dans le code. Ce conseil de programmation est-il maintenant obsolète ou est-il toujours utile?
Cela dépend un peu du moment où vous pensiez annuler la référence.
Si vous avez une chaîne d'objets A-> B-> C, une fois que A n'est pas joignable, A, B et C seront tous éligibles pour le ramassage des ordures (en supposant que rien d'autre ne se réfère à B ou C). Il n'est pas nécessaire, et n'a jamais été nécessaire, de définir explicitement les références A-> B ou B-> C sur null, par exemple.
En dehors de cela, la plupart du temps, le problème ne se pose pas vraiment car, en réalité, vous avez affaire à des objets de collections. En règle générale, vous devriez toujours penser à supprimer des objets de listes, de cartes, etc. en appelant la méthode appropriée remove ().
Le cas où il y avait autrefois un conseil de définir des références sur null était spécifiquement dans un longue portée où un objet gourmand en mémoire cesse d'être utilisé en cours de route dans la portée. Par exemple:
{
BigObject obj = ...
doSomethingWith(obj);
obj = null; <-- explicitly set to null
doSomethingElse();
}
La raison en était que, parce que obj est toujours dans la portée, alors sans l'annulation explicite de la référence, elle ne peut pas être récupérée avant la fin de la méthode doSomethingElse (). Et c'est le conseil que (ne tient probablement plus sur les machines virtuelles modernes): il s'avère que le compilateur JIT peut déterminer à quel moment une référence d'objet local donnée n'est plus utilisée.
Non, ce n'est pas un conseil obsolète. Les références pendantes posent toujours un problème, en particulier si vous implémentez, par exemple, un conteneur de tableau extensible (ArrayList
ou similaire) à l'aide d'un tableau préalloué. Les éléments dépassant la taille "logique" de la liste doivent être annulés, sinon ils ne seront pas libérés.
Voir Effective Java 2nd ed, élément 6: Suppression des références d'objet obsolètes.
Champs d'instance, éléments de tableau
S'il y a une référence à un objet, il ne peut pas être récupéré. Surtout si cet objet (et tout le graphique derrière lui) est gros, il n'y a qu'une seule référence qui arrête le ramassage des ordures, et cette référence n'est plus vraiment nécessaire, c'est une situation regrettable.
Les cas pathologiques sont l’objet qui conserve une instance non uniforme dans l’ensemble de l’arborescence DOM XML utilisée pour la configurer, le MBean non désenregistré ou la référence unique à un objet provenant d’une application Web non déployée empêchant le déchargement de tout un chargeur de classes. .
Donc, à moins que vous ne soyez sûr que l'objet qui contient la référence elle-même sera nettoyé de toute façon (ou même à ce moment-là), vous devez supprimer tout ce dont vous n'avez plus besoin.
Variables de portée:
Si vous envisagez de définir une variable locale sur null avant la fin de sa portée, afin de pouvoir la récupérer par le ramasse-miettes et de la marquer comme "inutilisable à partir de maintenant", vous devriez plutôt la placer dans une portée plus limitée. .
{
BigObject obj = ...
doSomethingWith(obj);
obj = null; // <-- explicitly set to null
doSomethingElse();
}
devient
{
{
BigObject obj = ...
doSomethingWith(obj);
} // <-- obj goes out of scope
doSomethingElse();
}
Les scopes longs et plats nuisent généralement à la lisibilité du code. L'introduction de méthodes privées pour casser les choses juste dans ce but n'est pas rare, aussi.
Dans les environnements à mémoire restreinte (par exemple, les téléphones cellulaires), cela peut être utile. En définissant null, l'objet n'a pas besoin d'attendre que la variable soit sortie de la portée pour être gc'd.
Toutefois, cela ne devrait pas être la règle pour la programmation quotidienne, sauf dans des cas particuliers comme celui cité par Chris Jester-Young.
Premièrement, cela ne signifie absolument pas que vous définissez un objet sur null
. Je l'explique ci-dessous:
List list1 = new ArrayList();
List list2 = list1;
Dans le segment de code ci-dessus, nous créons le nom de variable de référence d'objet list1
de ArrayList
objet stocké dans la mémoire. Donc, list1
fait référence à cet objet et il n’ya rien de plus qu’une variable. Et dans la deuxième ligne de code, nous copions la référence de list1
à list2
. Alors maintenant, revenons à votre question si je le fais:
list1 = null;
cela signifie que list1
ne fait plus référence à aucun objet stocké dans la mémoire, donc list2
n'aura également rien à faire. Donc, si vous vérifiez la taille de list2
:
list2.size(); //it gives you 0
Alors arrive ici le concept de ramasse-miettes qui dit «tu n'as pas à t'inquiéter de libérer la mémoire qui est tenue par l'objet, je le ferai quand je découvrirai qu'il ne sera plus utilisé dans le programme et que JVM me gérera»
J'espère que ça efface le concept.
Une des raisons est de supprimer les références d'objet obsolètes. Vous pouvez lire le texte ici.