On pense généralement que les objets nouveaux sont tous alloués sur le tas, mais ce n'est pas complètement correct. Grâce à l'analyse du processus d'allocation d'objets Java, nous avons constaté qu'en plus d'être alloué sur le tas, les objets peuvent également allouer de l'espace dans la pile ou le TLAB. La base technique pour allouer des objets sur la pile est l'analyse d'évasion et le remplacement scalaire. Cet article présente principalement l'analyse d'évasion.
Définition de l'analyse d'évasion
L'analyse d'échappement est un algorithme de l'analyse du flux de données interfonctionnel de données qui peut réduire efficacement la pression d'allocation de charge et de tas de mémoire synchrone dans les programmes Java.
Grâce à l'analyse d'évasion, le compilateur Java Hotspot peut analyser l'étendue de l'utilisation de la référence d'un nouvel objet et déterminer l'opportunité d'allouer l'objet au tas.
Java prend en charge et permet les options d'analyse d'échappement dans les versions Java SE 6U23 et ultérieures. Le compilateur Java Hotspot Jit peut effectuer une analyse d'échappement du code lorsque la méthode est surchargée ou chargée dynamiquement.
Le comportement de base de l'analyse d'évasion est d'analyser la portée dynamique d'un objet: lorsqu'un objet est défini dans une méthode, il peut être référencé par une méthode externe.
Échappement de la méthode: par exemple, passez en tant que paramètre d'appel à d'autres méthodes.
Échappement du thread: il est accessible par des threads externes, tels que l'attribution de valeurs aux variables de classe ou aux variables d'instance qui peuvent être accessibles dans d'autres threads.
Base théorique de l'analyse d'évasion
L'analyse d'évasion est effectuée sur la base de l'algorithme décrit par Jong-Deok Choi, Manish Gupta, Mauricio Seffano, Vugramam C. Sreedhar, Sam Midkiff et autres dans le document "Escape Analysis for Java".
Cet algorithme introduit un graphique connecté et utilise le graphique connecté pour construire la relation accessible entre l'objet et la référence d'objet, et sur la base de cela, une méthode d'analyse de flux de données combinée est proposée. Étant donné que l'algorithme est dépendant du contexte et sensible au flux et simule les relations imbriquées à n'importe quel niveau de l'objet, la précision de l'analyse est élevée, mais le temps d'exécution et la consommation de mémoire sont relativement importants.
La plupart des implémentations de l'analyse d'évasion sont basées sur la prémisse du «monde fermé»: toutes les méthodes possibles exécutées ont été connues avant l'analyse d'évasion, et le fonctionnement réel du programme ne modifiera pas la relation d'appel entre eux. Mais lorsqu'un véritable programme Java fonctionne, ces hypothèses ne sont pas vraies. De nombreuses fonctionnalités des programmes Java, telles que le chargement dynamique des classes, l'appel des fonctions locales et la réflexion sur les appels du programme, briseront la convention dite "monde fermé".
Opérations de traitement après analyse d'évasion
Après analyse d'évasion, trois états d'évasion possibles de l'objet peuvent être obtenus:
Globalscape: c'est-à-dire que la référence d'un objet échappe à une méthode ou un thread. Par exemple, la référence d'un objet est copiée dans une variable de classe, ou stockée dans un objet qui s'est échappé, ou la référence de l'objet est renvoyée à la méthode d'appel comme valeur de retour de la méthode.
Argescape (Échappement au niveau des paramètres): c'est-à-dire l'application de l'objet transmis à une méthode pendant le processus d'appel de la méthode. Cet état peut être déterminé en analysant le code binaire de la méthode à régler.
Noescape: un objet qui peut être remplacé par des scalaires. L'objet peut ne pas être alloué sur un tas traditionnel.
Le compilateur peut utiliser les résultats de l'analyse d'évasion pour optimiser le programme:
L'objet d'allocation de tas devient un objet d'allocation de pile: un objet dans une méthode, et la référence de l'objet ne s'échappe pas, donc cette méthode peut être allouée sur la mémoire de la pile et est très fréquente à la mémoire du tas.
Éliminer la synchronisation: le coût de la synchronisation du thread est assez élevé et les conséquences de la synchronisation sont réduites de la concurrence et des performances. L'analyse d'échappement peut déterminer si un objet est toujours accessible par un seul thread. S'il est accessible par un seul thread, le fonctionnement de synchronisation de l'objet peut être converti en opération sans protection de synchronisation, ce qui peut considérablement améliorer le degré de concurrence et de performance.
Substitution vectorielle: méthode d'analyse d'échappement Si vous constatez que la structure de stockage de la mémoire de l'objet n'a pas besoin d'être effectuée en continu, vous pouvez économiser des pièces et même tout l'objet dans les registres du CPU, ce qui peut considérablement améliorer la vitesse d'accès.