CodeGym /Blog Java /Random-FR /Cycle de vie des objets
Auteur
John Selawsky
Senior Java Developer and Tutor at LearningTree

Cycle de vie des objets

Publié dans le groupe Random-FR
Salut! Je pense que vous ne seriez pas très surpris si je vous disais que votre ordinateur a une quantité de mémoire limitée :)
Cycle de vie des objets - 1
Même votre disque dur (qui fait beaucoup, beaucoup de fois la taille de la RAM) peut être plein à craquer de vos jeux, émissions de télévision et autres choses préférés. Pour éviter que cela ne se produise, vous devez surveiller l'état actuel de la mémoire de votre ordinateur et supprimer les fichiers inutiles. Comment tout cela est-il lié à la programmation Java ? Tout à fait directement ! Après tout, la création d'un objet oblige la machine Java à lui allouer de la mémoire . Un grand programme du monde réel crée des dizaines ou des centaines de milliers d'objets, et un morceau de mémoire est alloué pour chacun d'eux. Mais qu'en pensez-vous, combien de ces objets existent ? Sont-ils "vivants" pendant toute la durée de notre programme ? Bien sûr que non. Même avec tous leurs avantages, les objets Java ne sont pas immortels :) Les objets ont leur propre cycle de vie. Aujourd'hui, nous allons faire une petite pause dans l'écriture du code et explorer ce processus :) C'est également très important pour comprendre le fonctionnement d'un programme et pour gérer les ressources. Alors, où commence la vie d'un objet ? Comme un humain, dès sa naissance, c'est-à-dire lorsqu'il est créé.

Cat cat = new Cat();// Our Cat object's lifecycle begins now!
Premièrement, la machine virtuelle Java alloue la mémoire nécessaire pour créer l'objet. Ensuite, il crée une référence à celui-ci (dans notre cas, cat) pour permettre d'en garder une trace. Ensuite, toutes les variables sont initialisées, le constructeur est appelé et notre nouvel objet vit maintenant sa propre vie :) Les durées de vie des objets varient. Il n'y a pas de chiffres exacts ici. Dans tous les cas, un objet vit dans le programme et remplit ses fonctions pendant une certaine période de temps. Pour être précis, l'objet est "vivant" tant qu'il y a des références à lui. Dès qu'il n'y a plus de références, l'objet "meurt". Par exemple:

public class Car {
  
   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}
Dans la main()méthode, l'objet Car "Lamborghini Diablo" cesse d'être vivant sur la deuxième ligne. Il n'y avait qu'une seule référence à celle-ci, et la référence était définie sur null. Puisqu'il ne reste aucune référence au Diablo, il devient "poubelle". Une référence n'a pas besoin d'être définie sur zéro pour que cela se produise :

public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}
Ici, nous avons créé un deuxième objet et l'avons affecté à la référence lamborghini. Maintenant, deux références pointent vers l' Lamborghini Gallardoobjet, mais l' Lamborghini Diabloobjet n'en a aucune. Cela signifie que l' Diabloobjet devient poubelle. C'est à ce moment que le ramasse-miettes intégré (GC) de Java entre en jeu.
Cycle de vie des objets - 2
Le ramasse-miettes est un mécanisme Java interne chargé de libérer de la mémoire, c'est-à-dire de supprimer les objets inutiles de la mémoire. Ce n'est pas pour rien que nous avons choisi de le représenter avec un robot aspirateur. Le ramasse-miettes fonctionne à peu près de la même manière : il « se déplace » dans votre programme en arrière-plan, récupérant les déchets. Vous n'avez pratiquement pas besoin d'interagir avec lui. Son travail consiste à supprimer les objets qui ne sont plus utilisés dans le programme. Ainsi, il libère de la mémoire pour d'autres objets. Vous souvenez-vous qu'au début de la leçon dont nous avons parlé dans la vraie vie, vous devez surveiller l'état de votre ordinateur et supprimer les anciens fichiers ? Si nous parlons d'objets Java, le ramasse-miettes le fait pour vous. Le ramasse-miettes est démarré plusieurs fois pendant l'exécution de votre programme : vous n'avez pas à l'appeler explicitement et à lui donner des commandes (bien que cela soit techniquement possible). Nous parlerons plus en détail du ramasse-miettes plus tard et analyserons son fonctionnement plus en détail. Lorsque le ramasse-miettes atteint un objet, juste avant qu'il ne soit détruit, la finalize()méthode spéciale de l'objet est appelée. Cette méthode peut être invoquée pour libérer certaines ressources supplémentaires utilisées par l'objet. La finalize()méthode appartient à la classe Object. En d'autres termes, il est similaire à equals(), hashCode()et toString()(que vous avez déjà rencontré). Chaque objet l'a . Cela diffère des autres méthodes en ce que... comment devrions-nous dire cela... c'est très volontaire. Nous entendons par là queil n'est pas toujours appelé avant la destruction d'un objet . La programmation est une activité très précise. Le programmeur dit à l'ordinateur de faire quelque chose, et l'ordinateur le fait. Je suppose que vous vous êtes habitué à ce genre de comportement, donc au début, il vous sera peut-être difficile d'accepter l'idée suivante : "Avant qu'un objet ne soit détruit, la méthode de la classe Object est appelée. Ou pas. Si nous avons de la chancefinalize() ! " Pourtant, c'est la réalité. La machine Java elle-même détermine s'il faut appeler finalize() au cas par cas. À titre expérimental, essayons d'exécuter le code suivant :

public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {

       for (int i = 0 ; i < 1000000; i++) {

           Cat cat = new Cat();
           cat = null;// The first object becomes available for garbage collection here
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("The Cat is destroyed!");
   }
}
Nous créons un Catobjet et, dans la ligne suivante, nous mettons à zéro la seule référence à celui-ci. Et nous le faisons un million de fois. Nous avons explicitement remplacé la finalize()méthode. Chaque fois qu'un Catobjet est détruit, il doit afficher une chaîne, un total d'un million de fois. Mais non! Pour être exact, sur mon ordinateur, il n'a été exécuté que 37346 fois ! En d'autres termes, ma machine Java a décidé d'appeler la finalize()méthode dans seulement 1 cas sur 27. Dans les autres cas, la récupération de place n'impliquait pas cet appel. Essayez d'exécuter ce code vous-même. Vous obtiendrez probablement un résultat différent. Comme vous pouvez le constater, il est difficile d'appeler finalize()un partenaire fiable :) Alors, voici un petit conseil pour l'avenir : ne vous fiez pas à la finalize()méthode pour libérer des ressources critiques.La JVM peut l'appeler ou non. Qui sait? Si votre objet contenait des ressources critiques pour les performances (par exemple, une connexion à une base de données ouverte) alors qu'il était actif, il serait préférable de créer et d'appeler explicitement une méthode spéciale pour les libérer lorsque l'objet n'est plus nécessaire. De cette façon, vous saurez avec certitude que les performances de votre programme ne souffriront pas. Nous avons commencé par dire que travailler avec la mémoire et la récupération de place sont des sujets très importants, et ils le sont en effet. Une mauvaise gestion des ressources et une mauvaise compréhension de la manière dont les objets inutiles sont nettoyés peuvent entraîner l'un des bogues les plus désagréables : les fuites de mémoire . C'est l'une des erreurs de programmation les plus connues. Il a même son propre article Wikipedia. Un code mal écrit peut créer une situation dans laquelle la mémoire est allouée à chaque fois pour les objets nouvellement créés, mais les anciens objets inutiles ne sont pas disponibles pour la récupération de place. Puisque nous avons déjà fait l'analogie avec l'aspirateur robot, imaginez ce qui se passerait si, avant de faire fonctionner le robot, vous éparpilliez des chaussettes dans toute la maison, brisiez un vase en verre et laissiez des pièces de Lego partout sur le sol. Naturellement, le robot essaierait de faire quelque chose, mais un jour il se bloquera.
Cycle de vie des objets - 3
Pour que l'aspirateur fonctionne correctement, vous devez garder le sol en bon état et ramasser tout ce qu'il ne peut pas supporter. Le ramasse-miettes suit le même principe. Si un programme a beaucoup d'objets qu'il ne peut pas nettoyer (comme une chaussette ou un Lego pour notre robot aspirateur), un jour nous manquerons de mémoire. Non seulement votre programme se bloquera, mais tous les autres programmes qui s'exécutent sur l'ordinateur le seront également. Après tout, ils n'auront pas non plus assez de mémoire (pour en revenir à notre analogie, le verre brisé sur le sol arrête non seulement l'aspirateur, mais aussi les personnes qui vivent dans la maison). En bref, voici à quoi ressemblent le cycle de vie des objets et la récupération de place en Java. Vous n'avez pas besoin de mémoriser cela : il suffit simplement de comprendre comment cela fonctionne. Dans la prochaine leçon, nous Je reviendrai plus en détail sur ces processus. Mais pour l'instant, vous pouvez retourner à la résolution des tâches CodeGym :) Bonne chance !
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION