Explication détaillée de JVM dans un article

Explication détaillée de la JVM

Récemment, j'ai étudié : "Compréhension approfondie de la programmation à haute concurrence" de Zhou Zhiming ;;
Par la présente, je résume brièvement certains des apprentissages pour faciliter l'amélioration et la consolidation ultérieures des connaissances liées à la JVM ;
si vous souhaitez en savoir plus sur l'apprentissage, vous peut lire l'œuvre originale de référence ci-dessus ;

Zone mémoire Java et MOO

Zone de données d'exécution

Lorsque la machine virtuelle Java exécute un programme Java, elle divise l'espace mémoire qu'elle gère en plusieurs zones de données différentes.

Ces zones ont leurs propres objectifs, temps de création et de destruction

La mémoire gérée par la machine virtuelle Java comprendra les zones de données d'exécution suivantes :

Insérer la description de l'image ici

  1. compteur de programme

    Une zone mémoire plus petite qui peut être considérée comme un indicateur de numéro de ligne du bytecode exécuté par le thread actuel.

    Dans le modèle conceptuel de la machine virtuelle, l'interpréteur de bytecode sélectionne la prochaine instruction de bytecode à exécuter en modifiant la valeur de ce compteur.

    Étant donné que le multithreading des machines virtuelles Java est implémenté en changeant de thread et en allouant des tranches de temps CPU ; à un moment donné, un processeur (ou un cœur d'un processeur multicœur) n'exécutera que des instructions dans un seul thread. Par conséquent, afin de restaurer la position d'exécution correcte après un changement de thread, chaque thread a besoin d'un compteur privé ; les compteurs de chaque thread ne s'affectent pas les uns les autres et sont stockés indépendamment.

    Avis:

    ​ Si une méthode Java est exécutée, la valeur de ce compteur est l'adresse de l'instruction du bytecode de la machine virtuelle ;

    ​ Si la méthode Native est exécutée, cette valeur est vide ;

    ​ Cette zone est la seule où la situation du MOO n'est pas spécifiée dans la spécification de la machine virtuelle ;

  2. machine virtuelle Java

    La machine virtuelle Java est également privée du thread et a le même cycle de vie que le thread ;

    La pile de machine virtuelle décrit le modèle de mémoire d'exécution des méthodes Java : un cadre de pile est créé lorsque chaque méthode est exécutée, qui est utilisé pour stocker des tables de variables locales, des piles d'opérandes, des liens dynamiques, des sorties de méthode et d'autres informations.

    Le processus depuis l'appel jusqu'à la fin de l'exécution de chaque méthode correspond au processus d'un cadre de pile depuis son insertion dans la pile jusqu'à sa sortie de la pile de la machine virtuelle ;

    La table de variables locales stocke divers types de données de base et références d'objets connus du compilateur ; l'espace mémoire requis par la table de variables locales sera alloué une fois la période de compilation terminée ;

    Dans la spécification de la machine virtuelle Java, cette zone spécifie deux exceptions pouvant se produire :

    1. StackOverflowError : la profondeur de pile demandée par le thread est supérieure à la profondeur de pile virtuelle autorisée ;

    2. OutofMemorryError : la plupart des piles de machines virtuelles peuvent être étendues de manière dynamique. Si une mémoire suffisante ne peut pas être demandée pendant l'expansion, cette exception sera levée ;

  3. pile de méthodes natives

    L'effet sur la pile de machines virtuelles est similaire, la plus grande différence est :

    La pile de machines virtuelles exécute les services de méthodes Java pour la machine virtuelle, tandis que la pile de méthodes locales exécute les services de méthodes natives pour la machine virtuelle ;

    Étant donné que la spécification de la machine virtuelle n'impose pas de piles de méthodes locales, des machines virtuelles spécifiques peuvent être implémentées librement. Certaines machines virtuelles (telles que Sun Hotspot) combinent directement la pile de méthodes locales et la pile de machines virtuelles en une seule ;

    La pile de méthodes locales est similaire à la pile de machines virtuelles et lancera également StackOverflowError et OutofMemorryError ;

  4. tas Java

    Pour la plupart des applications, le tas Java constitue la plus grande pièce de mémoire gérée par la machine virtuelle ;

    Le tas Java est une zone mémoire partagée par tous les threads et est créée au démarrage de la machine virtuelle Java ;

    Le seul but de cette zone mémoire est de stocker les instances d'objets , et presque toutes les instances d'objets allouent de la mémoire ici ;

    Le tas Java est la zone principale gérée par le garbage collector ;

    Du point de vue du recyclage de la mémoire, puisque les collecteurs actuels adoptent des algorithmes de collecte générationnelle, le tas Java peut également être subdivisé en : nouvelle génération et ancienne génération ;

    Pour être plus détaillé, elle peut être divisée en : zone Eden, zone From Survivor, To Survivor, etc.

    Le but de cette subdivision supplémentaire est le suivant : mieux récupérer la mémoire ou allouer de la mémoire plus rapidement ;

    Selon la spécification de la machine virtuelle Java, le tas Java peut se trouver dans un espace mémoire physiquement discontinu, à condition qu'il soit logiquement continu ;

    S'il n'y a pas de mémoire dans le tas pour l'allocation d'instance et que le tas ne peut pas être étendu, une exception OutofMemoryError sera levée ;

  5. zone de méthode

    La zone de méthode, comme le tas Java, est une zone mémoire partagée par chaque thread ;

    Utilisé pour stocker des données telles que des informations de classe, des constantes, des variables statiques, du code compilé par le compilateur juste à temps, etc. qui ont été chargées par la machine virtuelle ;

    La spécification de la machine virtuelle Java a des restrictions très lâches sur la zone de méthode. En plus de ne pas nécessiter d'espace continu comme le tas et d'avoir l'option de taille fixe ou d'extensibilité,

    Vous pouvez également choisir de ne pas implémenter le garbage collection.

    Les comportements de collecte des déchets sont relativement rares dans ce domaine.Le recyclage de la mémoire dans ce domaine concerne principalement le recyclage des pools constants et le déchargement des types ;

    Selon la spécification de la machine virtuelle Java, lorsque la zone de méthode ne peut pas répondre aux exigences d'allocation de mémoire, une exception OutofMemoryError sera levée ;

  6. Pool constant d’exécution

    Le pool de constantes d’exécution fait partie de la zone des méthodes ;

    En plus des informations descriptives telles que la version de la classe, les champs, les interfaces, les méthodes, etc., le fichier Class dispose également d'un pool de constantes , qui est utilisé pour stocker divers littéraux et références de symboles générés lors de la compilation. Cette partie du contenu sera chargé lorsque la classe est chargée.Après cela, entrez le pool de constantes d'exécution dans la zone de méthode ;

    Une autre caractéristique du pool de constantes d'exécution pour le pool de constantes de fichiers de classe est qu'il est dynamique :

    Le langage Java n'exige pas que les constantes soient générées lors de la compilation, c'est-à-dire que le contenu du pool de constantes qui n'est pas prédéfini dans le fichier Class peut entrer dans le pool de constantes d'exécution ; les constantes peuvent également être placées dans le pool pendant l'exécution ; ceci fonctionnalité est exploitée La plus courante est la méthode intern() de la classe String ;

    (Après avoir appelé intern(), vérifiez d'abord s'il existe une référence à l'objet dans le pool de constantes de chaîne . S'il existe, renvoyez la référence à la variable, sinon ajoutez la référence et renvoyez-la à la variable)

  7. mémoire directe

    La mémoire directe n'est pas la zone de données d'exécution de la machine virtuelle, ni la zone de mémoire définie dans la spécification de la machine virtuelle Java, mais cette partie de la mémoire est également fréquemment utilisée et peut également provoquer une exception OutofMemoryError ;

    Évidemment, l'allocation de mémoire directe native ne sera pas limitée par la taille du tas Java, mais puisqu'il s'agit de mémoire, elle sera certainement limitée par la taille totale de la mémoire de la machine native et l'espace d'adressage du processeur ;

    Lors de la configuration des paramètres de la machine virtuelle, la mémoire directe est ignorée, ce qui entraîne que la somme de chaque zone de mémoire est supérieure à la limite de mémoire physique, ce qui entraîne une exception OutofMemoryError lors de l'expansion dynamique ;

Exception réelle d'erreur de mémoire insuffisante

Dans la spécification de la machine virtuelle Java, en plus du compteur de programme, plusieurs autres zones de données d'exécution ont la possibilité d'exceptions OutofMemoryError.Ensuite, nous vérifierons les scénarios d'occurrence d'exceptions à travers plusieurs exemples et présenterons plusieurs paramètres de machines virtuelles liées à la mémoire;

Introduisez d’abord quelques paramètres JVM :

  1. -Xms : définit la taille initiale de la mémoire du segment JVM
  2. -Xmx : définit la taille maximale de la mémoire du segment JVM
  3. -Xmn : Définir la taille de la jeune génération
  4. -Xss : définit la taille de la pile de chaque thread
  5. -XX:+HeapDumpOnOutofMemoryError : lorsqu'une exception MOO se produit, un fichier de vidage de tas est généré
  6. -XX:HeapDumpPatch=patch : stocke le chemin du fichier de vidage du tas généré ; par exemple -XX:HeapDumpPath=F:\books
  7. -XX:+PrintGCDetails : Imprimer les informations détaillées du GC
  8. -XX:+PrintGCTimeStamps : imprimer les horodatages GC
  9. -XX:MetaspaceSize : définit la taille du métaespace pour déclencher le garbage collection
  10. -XX:MaxMetaspaceSize : définit la valeur maximale du métaespace

Simulation réelle de l'exception MOO :

Les exemples de codes ci-dessous sont tous exécutés sur la base de la machine virtuelle Hotspot de SUN. Pour différentes versions de machines virtuelles de différentes sociétés, les paramètres et les résultats d'exécution peuvent être différents ;

  1. Débordement de tas Java

    Le tas Java est utilisé pour stocker des objets. Tant que les objets sont créés en continu et qu'il existe un chemin accessible entre les routes GC et les objets pour éviter que le mécanisme de récupération de place n'efface ces objets, une fois que la mémoire occupée par l'objet atteint le tas maximum limite de capacité, une exception MOO se produira ;

    Dans l'exemple de code, la taille du tas Java est limitée à 20 Mo et ne peut pas être étendue (définissez la valeur minimale du paramètre -Xms du tas et la valeur maximale du paramètre -Xmx pour qu'ils soient identiques pour éviter l'expansion automatique du tas), et passez les paramètres -XX:+HeapDumpOnOutOfMemoryError, -XX: HeapDumpPath=F:\books permettent à la machine virtuelle de vider l'instantané de vidage de la mémoire tas actuel lorsqu'une exception MOO se produit et de l'enregistrer à l'emplacement spécifié pour une analyse ultérieure ;

    Dans l'exemple de code, nous définissons les paramètres de la machine virtuelle comme suit :

Insérer la description de l'image ici

Exemple de code :

/**
 * @author Snow
 * Java堆OOM异常模拟
 */
public class HeapOomDemo {
    
    

    static class OomTest{
    
    }

    public static void main(String[] args) {
    
    
        ArrayList<OomTest> oomTests = new ArrayList<>();
        while (true){
    
    
            oomTests.add(new OomTest());
        }
    }
}

Exécutez le code et les résultats sont les suivants :

java.lang.OutOfMemoryError: Java heap space
Dumping heap to F:\books\java_pid11132.hprof ...
Heap dump file created [28150606 bytes in 0.068 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3210)
	at java.util.Arrays.copyOf(Arrays.java:3181)
	at java.util.ArrayList.grow(ArrayList.java:265)
	at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
	at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
	at java.util.ArrayList.add(ArrayList.java:462)
	at jvm.HeapOomDemo.main(HeapOomDemo.java:16)

Il ressort des résultats d'exécution qu'une exception MOO s'est produite et qu'un fichier de vidage a été généré sous le chemin de vidage configuré dans nos paramètres virtuels :

Insérer la description de l'image ici

Pour résoudre cette exception, nous devons d'abord analyser le fichier Dumped via l'outil d'analyse des impressions de mémoire. Ensuite, nous utilisons VisualVm de Java pour analyser ce fichier : Exécution en ligne de commande : jvisualvm

Insérer la description de l'image ici

Après avoir exécuté la commande, l'outil VisualVm s'ouvrira et nous importerons le fichier précédent :

Insérer la description de l'image ici

Après avoir importé et analysé le fichier Dump, vous pouvez voir les résultats d'analyse suivants :

Insérer la description de l'image ici

  1. Pile de machines virtuelles et débordement de pile de méthodes locales

    Puisqu'il n'y a aucune distinction entre la pile de machine virtuelle et la pile de méthodes locales dans la machine virtuelle Hotspot, pour la machine virtuelle Hotspot, bien que le paramètre -Xoss (taille de la pile de méthode locale) existe, il n'est en réalité pas valide. La capacité de la pile est uniquement déterminée par -Xss Paramètres des paramètres.

    Pour la pile de machines virtuelles et la pile de méthodes locales, la spécification de machine virtuelle Java définit deux exceptions :

    1. Si la profondeur de pile demandée par le thread est supérieure à la profondeur maximale autorisée par la machine virtuelle, une exception StackOverflowError sera levée.
    2. Si la machine virtuelle ne peut pas demander suffisamment d'espace mémoire lors de l'extension de sa mémoire, une exception OutofMemoryError sera levée.

    Dans l'exemple suivant, l'expérience est limitée aux opérations dans un seul thread :

    1. Utilisez le paramètre -Xss pour réduire la capacité de la mémoire de la pile ; résultat : une StackOverflowError est levée et lorsqu'une exception se produit, la profondeur de la pile de sortie est réduite en conséquence.
    2. Un grand nombre de variables locales sont définies, augmentant la longueur de la table de variables locales dans ce cadre de méthode ; résultat : StackOverflowError est levée et la profondeur de la pile de sortie est réduite en conséquence.

    Exemple de code :

    public class StackSomDemo {
          
          
    
        static class SomTest{
          
          
            private int stackLength = 1;
    
            public void stackLeak(){
          
          
                stackLength ++;
                stackLeak();
            }
        }
    
        public static void main(String[] args) {
          
          
            SomTest somTest = new SomTest();
            try {
          
          
                somTest.stackLeak();
            }catch (Throwable e){
          
          
                System.out.println("stack length:"+somTest.stackLength);
                throw e;
            }
    
        }
    }
    

    En exécutant l’exemple de code, les résultats sont les suivants :

    stack length:982
    Exception in thread "main" java.lang.StackOverflowError
    	at jvm.StackSomDemo$SomTest.stackLeak(StackSomDemo.java:9)
    	at jvm.StackSomDemo$SomTest.stackLeak(StackSomDemo.java:10)
    	at jvm.StackSomDemo$SomTest.stackLeak(StackSomDemo.java:10)
    

    Les résultats d'exécution ci-dessus montrent que : dans un seul thread, que ce soit en raison d'un cadre de pile trop grand ou d'une capacité de machine virtuelle trop petite, lorsque la mémoire ne peut pas être allouée, la machine virtuelle lève une exception StackOverflowError ;

  2. Zone de méthode et débordement de pool constant d'exécution

  3. Débordement direct de la mémoire locale

Récupérateur de place et stratégie d'allocation de mémoire

Le sujet est-il mort ?

Presque toutes les instances d'objets en Java sont stockées dans le tas. Avant que le ramasse-miettes ne recycle les objets, la première chose est de déterminer lesquels de ces objets sont « vivants » et lesquels sont « morts » ;

comptage de références

Autrement dit, ajoutez un compteur de référence à l'objet. Chaque fois qu'il y a une référence à celui-ci, la valeur du compteur est incrémentée de un ; lorsque la référence expire, la valeur du compteur est décrémentée de un ;

A tout moment, un objet avec une valeur de compteur de 0 ne peut plus être utilisé et est compté comme un objet « mort ».

La méthode de comptage de références est simple à mettre en œuvre et présente une efficacité de détermination élevée ; cependant, il est difficile de résoudre le problème des références circulaires entre les objets, elle est donc rarement utilisée dans les machines virtuelles traditionnelles.

Exemple de code :

//-XX:+PrintGCDetails,配置此选项打印GC信息
public class RefCountDemo {
    
    
    public Object instance = null;
    public static final int _1MB = 1024*1024;
    /**
     * 占用内存,便于GC日志查看是否被回收
     */
    private byte[] bigSize = new byte[2 *_1MB];

    public static void main(String[] args) {
    
    
        RefCountDemo objA = new RefCountDemo();
        RefCountDemo objB = new RefCountDemo();
        objA.instance = objB;
        objB.instance = objA;

        objA = null;
        objB = null;

        //假设这行发生GC,objA和objB能否被回收
        System.gc();
    }

}

En exécutant le code ci-dessus, les résultats sont les suivants :

[GC (System.gc()) [PSYoungGen: 9359K->728K(153088K)] 9359K->736K(502784K), 0.0007083 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 728K->0K(153088K)] [ParOldGen: 8K->588K(349696K)] 736K->588K(502784K), [Metaspace: 3116K->3116K(1056768K)], 0.0030812 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 153088K, used 3947K [0x0000000715f00000, 0x0000000720980000, 0x00000007c0000000)
  eden space 131584K, 3% used [0x0000000715f00000,0x00000007162daf90,0x000000071df80000)
  from space 21504K, 0% used [0x000000071df80000,0x000000071df80000,0x000000071f480000)
  to   space 21504K, 0% used [0x000000071f480000,0x000000071f480000,0x0000000720980000)
 ParOldGen       total 349696K, used 588K [0x00000005c1c00000, 0x00000005d7180000, 0x0000000715f00000)
  object space 349696K, 0% used [0x00000005c1c00000,0x00000005c1c93208,0x00000005d7180000)
 Metaspace       used 3161K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 342K, capacity 388K, committed 512K, reserved 1048576K

Comme le montrent les résultats d'exécution ci-dessus, le journal GC contient « 9359K->728K », ce qui signifie que la machine virtuelle n'a pas recyclé les deux objets ci-dessus car ils se sont référencés ; cela montre également que la machine virtuelle actuelle ne utiliser le comptage de références.Déterminer si l'objet est vivant.

Algorithme d'analyse d'accessibilité

Dans les implémentations courantes des langages de programmation commerciaux traditionnels, l'analyse d'accessibilité est utilisée pour déterminer la survie des objets.

L'idée principale de l'algorithme d'analyse d'accessibilité est la suivante : utiliser une série d'objets appelés "GC-Racines" comme point de départ, et rechercher vers le bas à partir de ces points de départ. Le chemin parcouru par la recherche est appelé "chaîne de référence" ; lorsqu'un objet atteint le GC-Roots n'est connecté à aucune chaîne de référence (en termes de théorie des graphes, l'objet est inaccessible à GC-Roots), alors l'objet est déterminé comme inutilisable.

Comme le montre le diagramme d'exemple, bien que les objets obj5/obj6/obj7 soient liés les uns aux autres, ils ne sont pas accessibles depuis les racines GC, ils sont donc déterminés comme étant des objets recyclables :

Insérer la description de l'image ici

Dans le langage Java, les objets pouvant être utilisés comme racines GC sont répartis dans les types suivants :

  1. Objets référencés dans la pile de machines virtuelles (table de variables locales dans le cadre de pile)
  2. Variables référencées par les attributs statiques de classe dans la zone de méthode
  3. Objets référencés par des constantes dans la zone méthode
  4. Objet référencé par JNI (de manière générale méthode Native) dans la pile de méthodes natives
Parlons encore des citations

Après JDK1.2, Java a élargi le concept de références et a divisé les références en quatre types : les références fortes, les références logicielles, les références faibles et les références virtuelles. La force de ces quatre références s'est progressivement affaiblie :

  1. Référence solide

    ​ Les références fortes sont similaires à "Object obj = new Object()" ; les objets omniprésents dans le code, tant que les références fortes existent toujours, les objets correspondants seront recyclés par GC ;

  2. Référence logicielle

    ​ Les références logicielles sont utilisées pour décrire certains objets utiles mais inutiles ; avant qu'une exception MOO ne se produise dans le système, l'objet pointé par la référence logicielle sera recyclé deux fois. S'il n'y a toujours pas assez de mémoire, une exception MOO sera levée.

  3. Faible référence

    ​ Utilisé pour décrire des objets non essentiels ; les objets associés à des références faibles ne peuvent survivre que jusqu'à ce que le prochain garbage collection ait lieu.

  4. Fantôme

    ​ Également connue sous le nom de référence fantôme ou référence fantôme, sa seule fonction est que lorsque l'objet associé est récupéré, il y aura une notification système ;

vie ou mort

Même dans l'algorithme d'analyse d'accessibilité, pour qu'un objet inaccessible soit réellement déclaré « mort », il doit passer par au moins deux processus de marquage :

  1. Si après l'analyse de l'accessibilité de l'objet, aucune chaîne de référence de GC Roots n'y est connectée, il sera marqué pour la première fois et filtré. La condition de filtrage est de savoir s'il est nécessaire que cet objet exécute la méthode finalize() :
    1. Lorsque l'objet ne couvre pas la méthode finalize(), ou que la méthode finalize() a été appelée par la machine virtuelle, cette situation est considérée comme « inutile à exécuter ».
    2. Si l'objet détermine qu'il est nécessaire d'exécuter la méthode finalize(), alors l'objet entrera dans une file d'attente F-Queue et sera exécuté ultérieurement par un thread Finalizer de faible priorité créé par la machine virtuelle ;
  2. La méthode finalize() est la dernière chance pour l'objet d'échapper au sort de la mort. Plus tard, le GC marquera l'objet dans la file d'attente F du tas deux fois à petite échelle. Si l'objet se sauvegarde dans la méthode finalize() - tant qu'il est connecté à la chaîne de référence, il suffit d'établir une association avec n'importe quel objet, par exemple en s'attribuant à une variable de classe ou à une variable membre de l'objet. Puis lorsqu'il est marqué pour la deuxième fois, il sera supprimé de la Collection « En passe d'être recyclée » ;

Algorithme de collecte des déchets

Algorithme de marquage et de balayage

L'algorithme de marquage-effacement est l'algorithme de collecte le plus basique, qui est principalement divisé en deux étapes : marquage et effacement :

  1. Marquez d’abord tous les objets qui doivent être recyclés
  2. Une fois le marquage terminé, les objets marqués sont uniformément recyclés

On l’appelle le plus basique car les algorithmes ultérieurs sont basés sur ses idées et améliorés pour combler ses lacunes.

Les principaux défauts de cet algorithme sont :

  1. Problèmes d'efficacité, les processus de marquage et de compensation ne sont pas très efficaces
  2. Problème d'espace, un grand nombre de fragments de mémoire seront générés une fois la marque effacée ; trop de fragments de mémoire peuvent entraîner la nécessité ultérieure d'allouer un espace objet plus grand.

Impossible de trouver suffisamment de mémoire contiguë et devez déclencher une autre action de garbage collection plus tôt

Algorithme de réplication

Afin de résoudre le problème d'efficacité, un algorithme appelé « copie » a émergé :

​ Il divise la mémoire disponible en deux blocs de taille égale en fonction de la capacité et n'en utilise qu'un à la fois. Lorsque ce bloc de mémoire est épuisé, copiez les objets survivants dans un autre bloc, puis nettoyez immédiatement l'espace mémoire utilisé.

Avantages et inconvénients:

Cela permet à chaque demi-zone d'être recyclée à chaque fois, et il n'est pas nécessaire de prendre en compte la fragmentation de la mémoire lors de l'allocation de mémoire. Il suffit de déplacer le pointeur supérieur sur la pile et d'allouer la mémoire dans l'ordre. C'est simple à mettre en œuvre et efficace à exécuter.

L'inconvénient est que cet algorithme réduit la mémoire à la moitié de la taille d'origine, ce qui est trop coûteux.

Remarque : les machines virtuelles commerciales utilisent désormais cet algorithme de collecte pour recycler la nouvelle génération. Les recherches spéciales d'IBM montrent que 98 % des objets de la nouvelle génération sont « vivants et meurent », il n'est donc pas nécessaire de suivre un ratio de 1 : 1. Divisez l'espace mémoire, mais divisez la mémoire en une zone Eden plus grande et deux zones Survivant plus petites, et utilisez Eden et l'une des zones Survivant à chaque fois . Lors du recyclage, copiez immédiatement les objets survivants d'Eden et du Survivant sur un autre Survivant, et enfin nettoyez Eden et le Survivant qui viennent d'être utilisés .

Le rapport de taille par défaut de la machine virtuelle Eden et Survivor for Hotspot est de 8:1 , c'est-à-dire que l'espace mémoire disponible dans chaque nouvelle génération représente 90 % (80 % + 10 %) de la capacité totale de la nouvelle génération, et seulement 10 % de la mémoire sera "gaspillée"".

Les 98 % d'objets pouvant être recyclés mentionnés ci-dessus ne sont que des données dans des scénarios généraux. Nous n'avons aucun moyen de garantir que pas plus de 10 % des objets survivront à chaque recyclage. Lorsque l'espace Survivant est insuffisant, vous devez compter sur une autre mémoire. (il s'agit ici de l'ancienne génération). ) pour la garantie de distribution.

Algorithme de regroupement de marques

Lorsque le taux de survie des objets est élevé, l'algorithme de collecte de copies effectuera davantage d'opérations de copie et l'efficacité deviendra moindre. Plus important encore, si vous ne voulez pas gaspiller 50 % de l'espace, vous devez disposer d'un espace supplémentaire pour la garantie d'allocation pour faire face à la situation extrême où tous les objets de la mémoire utilisée sont vivants à 100 %, donc cette méthode ne peut généralement pas être utilisé dans l'ancienne génération.

Selon les caractéristiques de la vieillesse, quelqu'un a proposé un algorithme de « tri par marquage » :

Le processus de marquage est toujours le même que l'algorithme "mark-clear", mais les étapes suivantes ne consistent pas à nettoyer directement les objets recyclables, mais à déplacer tous les objets survivants vers une extrémité, puis à nettoyer directement la mémoire à l'extérieur de l'extrémité. frontière.

Algorithme de collecte générationnelle

Le garbage collection actuel des machines virtuelles commerciales adopte tous l'algorithme de « collecte générationnelle », cet algorithme divise principalement la mémoire en plusieurs blocs selon les différents cycles de vie des objets. Généralement, le tas Java est divisé en nouvelle génération et ancienne génération ; de cette manière, l'algorithme de collecte le plus approprié peut être utilisé en fonction des caractéristiques de chaque génération.

Dans la nouvelle génération, lors de chaque garbage collection, on constate qu'un grand nombre d'objets sont morts et que seuls quelques-uns survivent.Ensuite, utilisez l'algorithme de copie, qui n'a besoin que de payer le coût de copie d'un petit nombre d'objets survivants pour terminer la collection.

Dans l'ancienne génération, parce que le taux de survie des objets est élevé et qu'il n'y a pas d'espace supplémentaire pour garantir son allocation, l'algorithme « mark-clean » ou « mark-organize » doit être utilisé pour le recyclage.

Éboueur

Si l'algorithme de garbage collection est la méthodologie de recyclage de mémoire, alors le collecteur est l'implémentation spécifique du recyclage de mémoire ;

Dans la spécification de la machine virtuelle Java, il n'y a pas de dispositions spécifiques sur la manière dont le collecteur implémente le recyclage de la mémoire. Par conséquent, les garbage collector implémentés par différents fabricants et différentes versions de machines virtuelles peuvent être très différents, et les paramètres de configuration sont généralement fournis aux utilisateurs pour qu'ils puissent les ajuster. selon leurs propres caractéristiques et besoins, pour combiner les collectionneurs nécessaires à chaque époque.

La machine virtuelle qui sera abordée ici est basée sur la machine virtuelle après JDK1.7 Update 14. Le collecteur inclus dans cette machine virtuelle est tel qu'illustré dans la figure ci-dessous :

Insérer la description de l'image ici

La figure ci-dessus montre les collecteurs en 7 qui agissent sur des générations différentes. S'il y a une connexion entre les deux collecteurs, cela signifie qu'ils peuvent être utilisés ensemble. La région où se trouvent les machines virtuelles indique si elles sont de la nouvelle génération ou de l'ancienne génération.

Avant de présenter ensuite ces collectionneurs, soyons clairs : même si nous comparons différents collectionneurs, nous n'essayons pas de sélectionner le meilleur collectionneur. Parce que jusqu'à présent, il n'existe pas de meilleur collecteur ni de collecteur universel, nous choisissons donc uniquement le collecteur le plus adapté à des scénarios d'application spécifiques.

Collecteur en série

Le collecteur Serial est le collecteur le plus basique et le plus ancien. C'était le seul collecteur de la nouvelle génération avant JDK1.3.

Comme son nom l'indique, ce collecteur est monothread, ce qui signifie non seulement qu'il utilisera un seul processeur et un seul thread pour effectuer le garbage collection, mais plus important encore, il doit suspendre tous les autres travaux pendant l'exécution du garbage collection. fil jusqu'à ce qu'il soit collecté.

"Arrêter le monde" est automatiquement lancé et complété par la machine virtuelle en arrière-plan. Cela entraînera l'arrêt de tous les threads utilisateur dans un certain laps de temps sans que l'utilisateur ne le voie. Ceci est problématique pour de nombreuses applications. C'est inacceptable.

La figure suivante montre le processus en cours d'exécution de la collection Serial/Serial Old :

Insérer la description de l'image ici

À partir du JDK1.3, l'équipe de développement de machines virtuelles Hotpost s'est engagée à éliminer ou à réduire les pauses causées par les threads de travail en raison du recyclage de la mémoire, du collecteur série au collecteur parallèle, en passant par le collecteur CMS et même le dernier collecteur G1. Le temps de pause des threads utilisateur continue de diminuer, mais il n'y a toujours aucun moyen de l'éliminer complètement (le collecteur dans RTJS n'est pas inclus ici)

Jusqu'à présent, le collecteur Serial reste le collecteur nouvelle génération par défaut pour les machines virtuelles fonctionnant en mode Client ; il présente également les caractéristiques des autres collecteurs : simple et efficace. Pour les environnements limités à un seul CPU, le collecteur Serial sans la surcharge de thread interaction, vous pouvez naturellement obtenir une efficacité de collecte monothread plus élevée en vous concentrant sur le garbage collection.

Par conséquent, le collecteur série est un bon choix pour les machines virtuelles utilisées en mode Client .

Collectionneur Parnew

Le collecteur Parnew est en fait une version multithread du collecteur Serial. En plus d'utiliser plusieurs threads pour le garbage collection, d'autres comportements incluent tous les paramètres de contrôle disponibles pour le collecteur Serial, les algorithmes de collecte, Stop the world, les règles d'allocation d'objets, le recyclage. stratégies, etc. Tout comme le collecteur série.

Le diagramme schématique du collecteur Parnew/Serial Old est le suivant :

Insérer la description de l'image ici

En plus de la collecte multithread, le collecteur Parnew est également le collecteur nouvelle génération de premier choix pour de nombreuses machines virtuelles fonctionnant en mode Serveur ; l'une des raisons qui n'a rien à voir avec les performances mais qui est très importante est : actuellement, à l'exception de le collecteur série, c'est le seul qui peut être utilisé avec le collecteur CMS.

Au cours de la période JDK1.5, le collecteur Hotspot, le premier collecteur véritablement concurrent, s'est rendu compte que le thread GC et le thread utilisateur (essentiellement) s'exécutaient en même temps pour la première fois. Cependant, CMS, en tant que collecteur d'ancienne génération, ne peut pas fonctionner conjointement avec le collecteur de récupération parallèle existant dans JDK 1.4 ; par conséquent, dans JDK 1.5, lors de l'utilisation de CMS comme collecteur d'ancienne génération, la nouvelle génération ne peut choisir que Serial ou Parnew. appareil.

Dans un environnement mono-CPU, le collecteur Parnew n'aura jamais de meilleurs résultats que le collecteur Serial ; même en raison de la surcharge d'interaction des threads , lorsque le collecteur Parnew est implémenté en multi-threads, il ne garantit pas des performances à 100 % dans un environnement à deux processeurs. -Environnement CPU.100% meilleur que le collecteur série ;

Bien entendu, à mesure que le nombre de cœurs de processeur augmente, le collecteur Parnew reste utile pour une utilisation efficace des ressources du GC.

Collecteur de récupération parallèle

Le collecteur de récupération parallèle est un collecteur de nouvelle génération, un collecteur qui utilise un algorithme de copie et un collecteur multi-thread parallèle. Il semble similaire au collecteur Parnew, alors quelles autres fonctionnalités a-t-il ?

La différence entre le collecteur Parallel Scavenge est que son objectif est différent des autres collecteurs : les collecteurs tels que CMS se concentrent davantage sur la réduction du temps de pause des threads utilisateur pendant le GC, tandis que Parallel Scavenge se concentre sur l'obtention d'un débit contrôlable ; le soi-disant débit . la quantité est : débit = temps du thread utilisateur en cours d'exécution/(temps du thread utilisateur en cours d'exécution + temps du thread GC en cours d'exécution)

Plus le temps de pause du thread utilisateur est court, plus il est adapté aux programmes qui doivent interagir avec l'utilisateur ; tandis qu'un débit élevé peut utiliser efficacement les ressources du processeur et convient principalement aux tâches qui fonctionnent en arrière-plan et ne nécessitent pas d'interaction avec l'utilisateur;

Le collecteur de récupération parallèle fournit deux paramètres pour un contrôle précis du débit :

  1. -XX:MaxGCpauscMillis : temps de pause maximal du garbage collection, la valeur du paramètre est un nombre de millisecondes supérieur à 0
  2. -XX:GCTimeRadio : taille du débit, la valeur du paramètre est un entier supérieur à 0 et inférieur à 100

En raison de sa relation étroite avec le débit, le collecteur de récupération parallèle est souvent appelé collecteur « axé sur le débit d'abord ».

Ancien collectionneur en série

Le collecteur Serial Old est la version ancienne génération du collecteur Serial. Il s'agit également d'un collecteur monothread et utilise l'algorithme « mark-sort » ;

L'intérêt principal de ce collecteur est également d'être utilisé par les machines virtuelles en mode Client ;

S'il est en mode Serveur, alors il a deux utilisations principales :

  1. Une utilisation est dans JDK1.5 et les versions précédentes, en tant qu'ancienne génération utilisée avec le collecteur de récupération Parallel ;
  2. Une autre utilisation est celle d'un plan de sauvegarde pour le collecteur CMS, utilisé lorsqu'une défaillance du mode simultané se produit dans une collecte simultanée.

Le mode de fonctionnement du collecteur Serial Old est illustré dans la figure ci-dessous (utilisé avec Serila) :

Insérer la description de l'image ici

Ancien collecteur parallèle

Parallel Old est la version ancienne génération du collecteur de récupération Parallel, utilisant le multi-threading et l'algorithme « mark-collation » ;

Ce collecteur n'était fourni que dans JDK1.6. Avant cela, le collecteur de récupération parallèle de la nouvelle génération ne pouvait être utilisé qu'avec le collecteur Serial Old de l'ancienne génération. Cependant, en raison de la collection d'ancienne génération à thread unique de Serial Old, il n'a pas pu être pleinement utilisé.Les avantages des processeurs multicœurs peuvent être un frein ;

Jusqu'à l'émergence de Parallel Old, le collecteur « débit d'abord » disposait enfin d'une véritable combinaison de collecteurs. Dans les situations où le débit est important et les ressources CPU sont sensibles, la combinaison Parallel scavenge/Parallel Old peut être donnée en priorité ;

Le schéma de fonctionnement du Parallel Scavenge/Parallel Old Collector est le suivant :

Insérer la description de l'image ici

Collecteur de cms

Le collecteur CMS (Concurrent Mark Sweep) est un collecteur qui vise à obtenir le temps de pause de recyclage le plus court possible ;

Actuellement, un grand nombre d'applications Java accordent une grande attention à la vitesse de réponse du serveur pour offrir une meilleure expérience : le collecteur CMS est très adapté aux besoins de telles applications ;

Comme son nom l'indique, le CMS est implémenté à l'aide de l'algorithme « mark-clear ». L'ensemble du processus est principalement divisé en quatre étapes :

  1. Marque initiale (marque initiale CMS)
  2. Marque concurrente (marque concurrente CMS)
  3. Remarque (remarque CMS)
  4. Balayage simultané CMS

Les deux étapes de marquage initial et de re-marquage nécessitent toujours « Stopper le monde ».

La marque initiale n'est qu'un objet qui peut être directement associé aux GC Roots sous la marque, et c'est très rapide ;

Le marquage simultané est le processus de traçage des racines GC ;

Le remarquage fait référence à la partie de l'enregistrement qui change en raison du fait que le thread utilisateur continue de s'exécuter lorsque le marquage simultané est corrigé ; le temps de pause dans cette phase est généralement légèrement plus long que le marquage initial, mais beaucoup plus court que la phase de marquage simultané ;

Étant donné que dans l'ensemble du processus, le thread GC travaille avec le thread utilisateur dans les phases de marquage et d'effacement simultanées les plus longues ; par conséquent, dans l'ensemble, le thread GC CMS est exécuté en même temps que le thread utilisateur ;

Grâce à la figure suivante, vous pouvez voir clairement le processus de fonctionnement du collecteur CMS :

Insérer la description de l'image ici

Le collecteur CMS est un excellent collecteur avec les avantages suivants : collecte simultanée et faible pause ; SUN l'appelle officiellement un collecteur « simultané à faible pause » ;

Mais le CMS est loin d’être parfait et présente trois défauts principaux :

  1. Le collecteur CMS est très sensible aux ressources CPU ;
  2. Le collecteur CMS ne peut pas gérer les « déchets flottants » ;
  3. La collecte CMS est implémentée à l'aide de l'algorithme « mark-and-clear », ce qui signifie qu'après la collecte, une grande quantité de fragments d'espace sera générée ;
Collecteur G1

Le collecteur G1 est un garbage collector côté serveur. La mission qui lui est confiée par la machine virtuelle Hotpot est de remplacer à l'avenir le collecteur CMS dans JDK1.5.

Par rapport aux autres collecteurs, le G1 présente les caractéristiques suivantes :

  1. Parallélisme et concurrence : G1 peut exploiter pleinement les avantages du multi-CPU et du multicœur pour raccourcir le temps d'arrêt du monde ; certains autres collecteurs doivent à l'origine suspendre les threads utilisateur pour effectuer des actions GC, mais G1 peut toujours autoriser les utilisateurs pour effectuer des actions GC pendant le GC. Le thread continue de s'exécuter ;
  2. Collection générationnelle : Comme pour les autres collections, la notion de collection générationnelle est toujours retenue dans G1 ;
  3. Intégration spatiale : D'une manière générale, G1 implémente le collecteur basé sur l'algorithme « mark-clear », ce qui évite la fragmentation de la mémoire provoquée par l'algorithme « mark-clear » utilisé par CMS ;
  4. Pauses prévisibles : il s'agit d'un avantage majeur de G1 par rapport au CMS : en plus de rechercher des pauses faibles, G1 peut également établir un modèle de pause faible prévisible ; il permet aux utilisateurs de spécifier clairement le temps passé sur une période de M millisecondes. sur GC ne dépasse pas N millisecondes, ce qui est presque déjà une caractéristique du garbage collector Java en temps réel (RTSJ).

Les collectionneurs avant G1 collectaient sur la base de la nouvelle génération et de l'ancienne génération, mais ce n'est plus le cas du G1.

Le collecteur G1 divise le tas Java en plusieurs régions indépendantes (Régions) de taille égale. Bien que les concepts de nouvelle génération et d'ancienne génération soient toujours conservés, la nouvelle génération et l'ancienne génération ne sont plus physiquement isolées. Elles font toutes partie de la Région (pas nécessairement consécutifs).

Le collecteur G1 peut établir un modèle de temps de pause prévisible, car il peut planifier d'éviter un garbage collection complet dans l'ensemble du tas Java. G1 suit la valeur de l'accumulation de déchets dans chaque région (la quantité d'espace obtenue par le recyclage et la valeur d'expérience du temps requis pour le recyclage). Une liste de priorités est maintenue en arrière-plan et la région ayant la plus grande valeur est recyclée en premier en fonction du temps de collecte autorisé (c'est l'origine du Garbage-first).

Cette méthode d'utilisation de Region pour diviser l'espace mémoire et donner la priorité au recyclage garantit que le collecteur G1 peut obtenir l'efficacité de recyclage la plus élevée possible dans un temps limité.

Dans le collecteur G1, la machine virtuelle utilise Remember Set pour éviter les analyses complètes du tas pour les références entre les régions ou les références d'objet entre la nouvelle génération et l'ancienne génération dans d'autres collecteurs ;

Chaque région de G1 a un jeu de mémorisation correspondant. Lorsque le programme écrit des données de type référence, la machine virtuelle génère d'abord une barrière d'écriture pour interrompre temporairement l'opération d'écriture et vérifie si l'objet pointé par référence appartient à une région différente (lors de la collecte générationnelle , Il s'agit de vérifier si l'objet de l'ancienne génération fait référence à l'objet de la nouvelle génération), si tel est le cas, enregistrez les informations de référence via CardTable dans l'ensemble de mémorisation de la région à laquelle appartient l'objet référencé ; lorsque le garbage collection est effectué, dans la plage d'énumération de la racine GC En ajoutant un Remember Set, vous pouvez vous assurer que l'ensemble du tas ne sera pas analysé et qu'il n'y aura aucune omission.

Si l'opération de maintien du Remember Set n'est pas comptée, le fonctionnement du collecteur G1 peut être grossièrement divisé en les opérations suivantes :

  1. marque initiale
  2. marquage simultané
  3. note finale
  4. Dépistage et recyclage

Le schéma de fonctionnement du collecteur G1 est grossièrement le suivant :

Insérer la description de l'image ici

Comprendre les journaux GC
0.144: [GC (System.gc()) [PSYoungGen: 9359K->696K(153088K)] 9359K->704K(502784K), 0.0180797 secs] [Times: user=0.00 sys=0.00, real=0.02 secs] 
0.162: [Full GC (System.gc()) [PSYoungGen: 696K->0K(153088K)] [ParOldGen: 8K->616K(349696K)] 704K->616K(502784K), [Metaspace: 3201K->3201K(1056768K)], 0.0034062 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 153088K, used 1316K [0x0000000715f00000, 0x0000000720980000, 0x00000007c0000000)
  eden space 131584K, 1% used [0x0000000715f00000,0x00000007160490d0,0x000000071df80000)
  from space 21504K, 0% used [0x000000071df80000,0x000000071df80000,0x000000071f480000)
  to   space 21504K, 0% used [0x000000071f480000,0x000000071f480000,0x0000000720980000)
 ParOldGen       total 349696K, used 616K [0x00000005c1c00000, 0x00000005d7180000, 0x0000000715f00000)
  object space 349696K, 0% used [0x00000005c1c00000,0x00000005c1c9a328,0x00000005d7180000)
 Metaspace       used 3208K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 348K, capacity 388K, committed 512K, reserved 1048576K

Le format de journal de chaque collecteur est déterminé par sa propre implémentation ; en d'autres termes, le format de journal de chaque collecteur peut être différent ;

Comme le montre le journal ci-dessus :

  1. 0,144 et 0,162 représentent respectivement l'heure à laquelle le GC se produit : la signification de ce nombre est le nombre de secondes qui se sont écoulées depuis le démarrage de la machine virtuelle.
  2. [GC et [Full GC, indiquent le type de pause de ce garbage collection, plutôt que de faire la distinction entre GC nouvelle génération et GC ancienne génération ; indiquant que ce GC est Stop-the-world.
  3. [GC (System.gc()) : Si la collection est déclenchée en appelant System.gc(), alors elle s'affiche comme ceci ;
  4. [PSYoungGen : indique le collecteur Parallege Scavenge utilisé et la zone de collecte est la nouvelle génération ;
  5. 9359K->696K(153088K) : Le changement de mémoire entre crochets indique la capacité utilisée de la zone mémoire avant GC -> la capacité utilisée de la zone mémoire après GC
  6. 9359K->704K (502784K) : la mémoire change en dehors des parenthèses, indiquant la capacité utilisée du tas Java avant GC -> la capacité utilisée du tas Java après GC
  7. [Times : user=0.00 sys=0.00, real=0.02 secs] : La signification ici est cohérente avec la sortie de la commande Linux Time, qui indique respectivement le temps CPU consommé en mode utilisateur, le temps CPU consommé en mode noyau et le temps vécu du début à la fin de l'opération. Temps d'horloge murale ; (La différence entre le temps CPU et le temps d'horloge murale : le temps d'horloge murale comprend divers temps d'attente non opérationnels, tels que l'attente des E/S du disque, l'attente du blocage des threads, etc. .; alors que le temps CPU n'inclut pas ces temps)
Résumé des paramètres du garbage collector

Vous trouverez ci-dessous quelques paramètres courants liés au garbage collection des machines virtuelles :

  1. UseSerialGC : valeur par défaut lorsque la machine virtuelle s'exécute en mode client ; activez ce commutateur et la combinaison Serial/Serial Old sera utilisée pour GC.
  2. UseParNewGC : Après ouverture, la combinaison ParNew/Serial Old sera utilisée pour GC.
  3. UseConcMarkSweapGC : après ouverture, la combinaison ParNew+CMS+Serial Old sera utilisée pour GC.
  4. UseParallelCG : après ouverture, utilisez la combinaison Parallege Scavenge+Serial Old pour GC
  5. SurvivorRatio : Le ratio de capacité de la zone Eden et de la zone Survivor dans la nouvelle génération, la valeur par défaut est 8
  6. PretenureSizeThreshOld : directement promu à la taille de l'ancienne génération
  7. MaxTenuringThreshOld : âge de l'objet directement promu à l'ancienne génération
  8. UseAdaptiveSizePolicy : Ajustez dynamiquement la taille des zones Java et l'âge d'entrée dans l'ancienne génération
  9. ParallelGCThreads : définissez le nombre de threads pour le recyclage de la mémoire lors du GC parallèle
  10. CMSInitiatingQccupancyFraction : définit l'occupation du collecteur CMS dans l'ancienne génération avant de déclencher le GC ; la valeur par défaut est 68 % ; valable uniquement pour le collecteur CMS.
  11. UseCMSCompactAtFullCollection : définissez si CMS effectuera une défragmentation de la mémoire après GC.
  12. CMSFullGCBeforeFraction : configurez le CMS pour qu'il effectue plusieurs GC, puis effectuez une défragmentation de la mémoire.

Stratégies d’allocation de mémoire et de recyclage

La gestion automatique de la mémoire du système Java peut finalement se résumer et se traiter automatiquement en deux problèmes : allouer de la mémoire aux objets et recycler la mémoire allouée aux objets ;

D'une manière générale, l'allocation mémoire des objets est allouée sur le tas. Les objets sont principalement alloués dans la zone Eden de la nouvelle génération. Si le tampon d'allocation de thread local est démarré, il sera alloué sur le TLAB selon la priorité du thread ; dans quelques cas, il peut également être alloué sur le tas. Directement alloués dans l'ancienne génération, les détails spécifiques de l'allocation dépendent du type de garbage collector actuellement utilisé, et sont également liés aux paramètres de configuration de la machine virtuelle.

Ensuite, nous expliquerons plusieurs règles courantes d'allocation de mémoire et vérifierons ces règles via du code.

  1. Les objets sont distribués en premier à Eden

    Dans la plupart des cas, les objets seront alloués dans la zone Eden de la nouvelle génération. Lorsque la zone Eden ne dispose pas de suffisamment d'espace pour l'allocation, la machine virtuelle lancera un GC mineur ;

    Quelle est la différence entre le GC mineur et le GC complet ?

    1. GC cénozoïque (GC mineur) : fait référence aux GC qui se produisent dans la nouvelle génération ; parce que la plupart des objets Java ont les caractéristiques de naître et de se détruire, les GC mineurs sont très fréquents et la vitesse de recyclage est également très rapide.
    2. GC d'ancienne génération (Major GC/Full GC) : fait référence aux GC qui se produisent dans l'ancienne génération ; lorsque les Major GC apparaissent, ils sont généralement accompagnés d'au moins un Minor GC (pas absolument, dans la stratégie de collecte du collecteur Parallege Scavenge, il y a est une stratégie directe du Major GC). La vitesse du Major GC est généralement plus de 10 fois plus lente que celle du Minor GC.
  2. Les gros objets entrent directement dans l’ancienne génération

    ​ Les objets dits volumineux font référence à des objets Java qui nécessitent une grande quantité de mémoire continue, généralement des chaînes et des tableaux très longs ; des objets volumineux apparaissent souvent, ce qui peut facilement provoquer le déclenchement anticipé du GC pour répondre à la demande lorsqu'il y a encore beaucoup d'espace en mémoire. Grand espace contigu pour "placer" cet objet

  3. Les objets à longue durée de vie entreront dans l'ancienne génération

    La machine virtuelle définit un compteur d'âge d'objet pour chaque objet. Si l'objet est né en Eden et survit toujours après avoir subi un GC mineur et peut être hébergé par le survivant, il sera déplacé vers la zone Survivant et l'âge sera défini. à 1 ; l'objet Chaque fois qu'un "GC Mineur" survit dans la zone Survivant, l'âge de l'objet augmente d'un an ; lorsque son âge augmente jusqu'à un certain niveau (15 ans par défaut), il sera promu à l'ancienne génération ;

    Quant au seuil d'âge pour la promotion à l'ancienne génération, il peut être configuré via le paramètre -XX:MaxTenuringThreshOld

  4. Détermination dynamique de l'âge des objets

    Afin de s'adapter aux conditions de mémoire des différents programmes, la machine virtuelle n'exige pas toujours que l'âge de l'objet atteigne un seuil avant de pouvoir être promu à l'ancienne génération ; si la taille de tous les objets du même âge dans Survivor dépasse l'espace mémoire du survivant, alors les objets qui sont supérieurs ou égaux à cet âge seront promus à l'ancienne génération ; pas besoin d'attendre que l'âge seuil de XX:MaxTenuringThreshOld soit atteint

  5. Garantie d'attribution des espaces

Surveillance des performances et dépannage

Outils de ligne de commande JDK

Outils de surveillance et de dépannage SUN JDK

  1. jps : JVM Process Status Tool, affiche tous les threads de machine virtuelle Hotspot dans le système
  2. jstat : outil de surveillance des statistiques JVM, utilisé pour collecter divers aspects des données d'exploitation des machines virtuelles
  3. jinfo : informations de configuration pour Java, affiche les informations de configuration de la machine virtuelle
  4. jmap : Memory Map pour Java : générer un instantané de vidage de mémoire de la machine virtuelle
  5. jhat : JVM Heap Dump Browser : utilisé pour analyser les fichiers Heap Dump, il créera un serveur Http/Html, permettant aux utilisateurs de visualiser les résultats de l'analyse sur le navigateur
  6. jstack : Stack Trace pour Java, affichant des instantanés de threads de machine virtuelle
jps : outil d'état des processus de machine virtuelle

JVM Process Status Tool, sa fonction est similaire à la commande UNIX ps :

​ Peut répertorier les processus de machine virtuelle en cours d'exécution et afficher le nom de la classe principale d'exécution de la machine virtuelle (Classe principale, la classe où se trouve la fonction principale), ainsi que l'ID unique de la machine virtuelle locale (Identifiant de machine virtuelle Lcoal, LVMID) de ces processus.

Bien que la fonction soit relativement simple, il utilise le plus fréquemment l'outil de ligne de commande du JDK, car la plupart des autres outils s'appuient sur le LVMID qu'il interroge pour déterminer quel processus de machine virtuelle surveiller ;

Format de commande :

jps [option] [identifiant de l'hôte]

Exemple d'exécution :

C:\Users\lixuewen>jps -l
12912 -- process information unavailable
13744 com.twsz.mom.oauth.OauthApplication
16128 org.jetbrains.jps.cmdline.Launcher
17216 com.twsz.mom.mm.MaterialApplication
19620 org.apache.catalina.startup.Bootstrap
21236 sun.tools.jps.Jps
10744 com.twsz.mom.system.SystemApplication
12344 com.twsz.mom.gateway.GatewayApplication
14280
11500 com.twsz.mom.prod.ProductionApplication
15196 org.jetbrains.jps.cmdline.Launcher

jps peut interroger l'état du processus de la machine virtuelle distante avec le service RMI activé via le protocole RMI. L'ID d'hôte est l'adresse IP de l'hôte distant enregistrée dans le registre RMI.

Principales options de la commande jps :

  1. -q : afficher uniquement le LVMID, omettre le nom de la classe principale
  2. -m : affiche uniquement les fonctions transmises à la fonction main() de la classe principale au démarrage de la machine virtuelle
  3. -l : affiche le nom complet de la classe principale. Si le processus exécute un package Jar, affiche le chemin Jar.
  4. -v : affiche les paramètres de la machine virtuelle lorsque le processus de la machine virtuelle démarre
jstat : outil de surveillance des statistiques des machines virtuelles

JVM Statistics Monitoring Tool, un outil permettant aux utilisateurs de surveiller diverses informations sur l'état d'exécution des machines virtuelles

Il peut afficher le chargement de classe, la mémoire, le garbage collection, la compilation JIT et d'autres données d'exploitation dans le processus de machine virtuelle locale ou distante. Il n'y a pas d'interface graphique GUI et seules des informations en texte brut sont fournies ;

Format de commande :

jstat [option vmid [intervalle [s|ms] ] [nombre] ]

Description du format :

  1. S'il s'agit d'une machine virtuelle locale, le vmid et le LVMID sont cohérents ; s'il s'agit d'une machine virtuelle distante, le format du vmid doit être :

    ​ [protocole :] [//] lvmid [ @hostname [: port] /servername ]

  2. interval et count représentent l'intervalle et le nombre de requêtes. Si la valeur par défaut est, cela signifie que la requête n'est effectuée qu'une seule fois ;

  3. Supposons que l'état du garbage collection du processus 10744 soit interrogé toutes les 250 millisecondes pour un total de 20 fois. La commande est la suivante :

    ​ jstat -gc 10744 250 20

  4. L'option indique les informations de la machine virtuelle à interroger, qui sont principalement divisées en trois catégories : chargement de classe, garbage collection et état de compilation du runtime.

    1. -class : surveillez le chargement de la classe, la quantité de déchargement, l'espace total et le temps de chargement
    2. -gc : Surveiller le garbage collection, le tas Java, etc.
      1. -gccapacity : se concentre principalement sur l'espace maximum et minimum utilisé dans chaque zone du tas Java
      2. -gcutil : se concentre principalement sur le pourcentage d'espace utilisé dans l'espace total
      3. -gccause : similaire au précédent, mais la raison du déclenchement du dernier GC sera affichée.
      4. -gcnew : Surveiller l'état du GC de nouvelle génération
      5. -gcold : Surveiller l'état du GC de l'ancienne génération
      6. -gcoldcapacity : principalement axé sur l'espace maximum et minimum utilisé dans l'ancienne génération
      7. -gcpermcapacity : se concentre principalement sur l'espace maximum et minimum utilisé par la génération persistante
    3. -compilateur : méthodes compilées de sortie JIT, informations chronophages et autres
    4. -printcompilation : méthodes de sortie compilées JIT

Exemple d'exécution :

C:\Users\lixuewen>jstat -gcutil 11500
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  0.00  95.10   5.35  40.95  94.34  91.10     45    1.481     5    1.436    2.917

Il ressort des résultats de l'exécution :

​ La zone Eden (E) nouvelle génération occupe 5,35% de l'espace, les deux zones Survivants (S0, S1) occupent 0% et 95,10% de leurs surfaces respectives, et l'ancienne génération (O) et la génération permanente (M) respectivement Utiliser 40,95 % et 94,34 % de l'espace ;

Depuis l'exécution du programme, le GC mineur (YGC) s'est produit 45 fois, avec une durée totale de 1,481 secondes, le GC complet (FGC) 5 fois, avec une durée totale de 1,436 secondes, et la durée totale de tous les GC (GCT) était 2,917 secondes.

jstat fournit un affichage en texte brut des informations d'exécution de la machine virtuelle, et l'outil suivant Virvul VM fournit une page d'affichage visuel, qui peut être plus intuitive.

jinfo:outil d'informations de configuration Java

Informations de configuration pour Java, vous pouvez visualiser et ajuster divers paramètres de la machine virtuelle en temps réel ;

Utilisez la commande jps -v pour afficher la liste des paramètres spécifiés affichés au démarrage de la machine virtuelle ; si vous souhaitez connaître les valeurs par défaut des paramètres qui ne sont pas affichés spécifiés, vous pouvez utiliser jinfo -flag pour interroger.

jinfo -sysprops peut imprimer le contenu de System.getProperties() du processus de la machine virtuelle ;

Après JDK1.6, la possibilité de modifier les paramètres de la machine virtuelle pendant l'exécution a été ajoutée. Vous pouvez utiliser -flag [+|-] name ou -flag name=value pour modifier certains des paramètres de la machine virtuelle qui sont accessibles en écriture pendant l'exécution .

Format de commande jinfo :

jinfo [option] pid

Exemple d'exécution :

C:\Users\lixuewen>jinfo -sysprops
Usage:
    jinfo [option] <pid>
        (to connect to running process)
    jinfo [option] <executable <core>
        (to connect to a core file)
    jinfo [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

where <option> is one of:
    -flag <name>         to print the value of the named VM flag
    -flag [+|-]<name>    to enable or disable the named VM flag
    -flag <name>=<value> to set the named VM flag to the given value
    -flags               to print VM flags
    -sysprops            to print Java system properties
    <no option>          to print both of the above
    -h | -help           to print this help message

C:\Users\lixuewen>jinfo -flag MetaspaceSize 11500
-XX:MetaspaceSize=21807104
jmap : outil de mappage de mémoire Java

Memory Map pour Java, utilisé pour générer des instantanés de vidage de tas (communément appelés fichiers de vidage de tas ou de vidage de tas) ; vous pouvez également utiliser ce qui précède

-XX:+HeapDumpOnOutofMemoryError paramètre de configuration, génère automatiquement un fichier dunp lorsque le MOO se produit ;

La commande jmap ne sert pas seulement à obtenir des fichiers de vidage, elle peut également interroger la file d'attente d'exécution finalisée, le tas Java et les détails de génération permanente tels que l'utilisation de l'espace et

Quel collecteur utiliser, etc.

Format de commande :

jmap [option] vmid

Les valeurs juridiques et significations de l’option sont les suivantes :

  1. -dump : génère un instantané de vidage du tas Java ; le format est : jmap -dump:live,format=b,file=heap.bin
  2. -finalizerinfo : affiche les informations sur l'objet en attente que le thread Finalizer exécute la méthode finalize dans F-QUEUE
  3. -heap : affiche les détails du tas Java ; valable uniquement sous Linux/Solaris
  4. -histo : Afficher les statistiques des objets dans le tas
  5. -permstat : utilisez ClassLoader comme calibre statistique pour afficher l'état de la mémoire de génération permanente
  6. -F : lorsque le processus de la machine virtuelle ne répond pas à la commande -dump, vous pouvez utiliser cette commande pour forcer un instantané de vidage ; valable uniquement sous Linux/Solaris

Exemple d'exécution :

C:\Users\snow>jmap -dump:live,format=b,file=heap.bin 11500
Dumping heap to C:\Users\snow\heap.bin ...
Heap dump file created
jhat : outil d'analyse d'instantanés de stockage de tas de machine virtuelle

JVM Heap Dump Browser, utilisé conjointement avec jmap, est utilisé pour analyser l'instantané de vidage de tas généré par jmap ;

jhat dispose d'un micro-serveur HTTP/HTML intégré. Une fois les résultats d'analyse du fichier de vidage générés, ils peuvent être visualisés avec un navigateur ;

Dans la pratique, jhat n'est généralement pas utilisé directement pour analyser les fichiers de dump, et ce pour deux raisons principales :

  1. L'analyse du vidage n'est généralement pas effectuée sur le serveur d'applications car l'analyse est un processus long et gourmand en ressources matérielles. Essayez d'analyser le fichier de vidage sur d'autres ordinateurs. Puisque l'analyse est effectuée sur d'autres ordinateurs, il n'est pas nécessaire d'être soumis à aux restrictions de l'outil de ligne de commande.
  2. La fonction d'analyse de jhat est relativement simple.Plus tard, nous présenterons Virtual VM et d'autres outils d'analyse professionnels pour obtenir des fonctions d'analyse plus puissantes et professionnelles.

Exemple d'exécution :

C:\Users\lixuewen>jhat heap.bin
Reading from heap.bin...
Dump file created Wed Dec 21 22:24:20 CST 2022
Snapshot read, resolving...
Resolving 9370112 objects...
Chasing references, expect 1874 dots..............................................................................................................................
Eliminating duplicate references..........................................................................................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

Une fois que « Le serveur est prêt » apparaît à l'écran, saisissez « http://localhost:7000/ » dans le navigateur pour voir les résultats de l'analyse :

Insérer la description de l'image ici

jstack : outil de traçage de pile Java

Stack Trace pour Java est utilisé pour générer un instantané de thread de la machine virtuelle au moment actuel (généralement appelé fichier threaddump ou fichier javacore) ;

Un instantané de thread est une collection de piles de méthodes exécutées par chaque thread de la machine virtuelle à l'heure actuelle. L' objectif principal de la génération d'un instantané de thread est de localiser la cause des longues pauses dans les threads , telles que les blocages entre les threads, les boucles infinies. , ou de longues périodes de temps lors de la demande d'interfaces externes. L'attente est une raison courante ;

Format de commande :

jstack [option] vmid

Les valeurs juridiques et significations de l’option sont les suivantes :

  1. -F : Forcer la pile de sortie lorsque la demande de sortie normale ne reçoit pas de réponse
  2. -l : en plus de générer la pile, afficher les informations de pièce jointe sur le verrou
  3. -m : Si une méthode native est appelée, la pile C/C++ peut être affichée

Exemple d'exécution :

C:\Users\snow>jstack -l 11500
2022-12-22 10:39:35
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.201-b09 mixed mode):

"Keep-Alive-Timer" #957 daemon prio=8 os_prio=1 tid=0x000000002f9d7800 nid=0x4f88 waiting on condition [0x000000007a37f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at sun.net.www.http.KeepAliveCache.run(KeepAliveCache.java:172)
        at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
        - None

"logback-2" #802 daemon prio=5 os_prio=0 tid=0x000000002f9e2800 nid=0x22b8 waiting on condition [0x000000006a67f000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000005d8c9c218> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
        - None

"com.alibaba.nacos.client.Worker.longPolling.fixed-10.38.102.16_8848-dev" #625 daemon prio=5 os_prio=0 tid=0x000000002f9d6000 nid=0x3d88 runnable [0x0000000057f1d000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
        - locked <0x0000000736e4c250> (a java.io.BufferedInputStream)
        at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)
        at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1587)
        - locked <0x0000000736e431a0> (a sun.net.www.protocol.http.HttpURLConnection)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)

Dans JDK1.5, la classe Thread a ajouté une méthode getAllStrackTraces() pour obtenir les objets StackTraceElement de tous les threads de la machine virtuelle ; en utilisant cette méthode, la plupart des fonctions de jatack peuvent être réalisées avec quelques lignes de code simples ; en pratique , cela peut être envisagé Créer une page d'administrateur et afficher les informations de la pile Java via le navigateur à tout moment

hsdis: jit génère le désassemblage du code

HSDIS est un plug-in de désassemblage pour le code compilé JIT de la machine virtuelle Hotpot officiellement fourni par SUN ; en termes simples, il s'agit d'un outil de décompilation ;

Outil de visualisation JDK

Jconsole est un outil de surveillance des machines virtuelles fourni depuis l'ère JDK1.5 ; VisualVM a été publié dans JDK1.6 Update 7 et est un outil de dépannage tout-en-un promu par SUN ;

jconsole : console de surveillance et de gestion Java

Jconsole est un outil de surveillance et de gestion visuelle basé sur JMX ;

  1. Démarrer jconsole

    ​ Après avoir démarré jconsole via "jconsole.exe" dans le répertoire JDK/bin, tous les processus de machine virtuelle exécutés sur la machine locale seront automatiquement recherchés et l'utilisateur n'a pas besoin d'utiliser jps pour interroger, comme le montre la figure ci-dessous ;

Insérer la description de l'image ici

Double-cliquez pour sélectionner un processus pour démarrer la surveillance ; vous pouvez également utiliser le « Processus distant » ci-dessous pour vous connecter au serveur distant et surveiller le processus de la machine virtuelle distante.

Insérer la description de l'image ici

Après avoir double-cliqué sur un thread spécifique, vous entrez dans l'interface principale de jconsole, qui comprend une présentation, la mémoire, les threads, les classes, le résumé de la VM et les MBeans ;

"Aperçu" affiche un aperçu des principales données de fonctionnement de l'ensemble de la machine virtuelle, y compris des graphiques de courbes de quatre types d'informations : "Utilisation de la mémoire du tas", "Threads", "Classes" et "Utilisation du processeur". Ces graphiques sont les mémoire, résumé des informations sur les threads et les onglets de classe ;

  1. Surveillance de la mémoire

    L'onglet "Mémoire" est équivalent à la commande visuelle jstat, utilisée pour surveiller l'évolution de la mémoire gérée par la machine virtuelle (heap Java et génération permanente) ;

Insérer la description de l'image ici

  1. Surveillance des threads

    L'onglet "Thread" est équivalent à la commande visuelle jstack. Lorsqu'un thread est en pause, vous pouvez utiliser cet onglet pour la surveillance et l'analyse ;

Insérer la description de l'image ici

visualvm : outil de dépannage visuel tout-en-un

VisualVM est de loin l'outil de surveillance et de dépannage d'exécution le plus puissant publié avec le JDK ;

La description officielle de VisualVM est « Tout-en-un », indiquant qu'en plus d'exécuter la surveillance et la gestion des erreurs, il fournit également de nombreuses autres fonctions, telles que l'analyse des performances, etc. ;

Un autre grand avantage de VisualVM est qu'il ne nécessite pas que le programme surveillé s'exécute sur la base d'un agent spécial, il a donc peu d'impact sur les performances réelles de l'application, ce qui lui permet d'être directement utilisé dans des environnements de production.

  1. Plage de compatibilité VisualVM et installation du plug-in

    ​ VisualVM est développé sur la base de la plate-forme NetBeans, il dispose donc dès le début de fonctionnalités d'extension de plug-in. Grâce à la prise en charge des extensions de plug-in, VisualVM peut faire :

    1. Afficher les processus de la machine virtuelle ainsi que les informations de configuration et d'environnement des processus (jps, jinfo)

    2. Surveillez les informations sur le CPU, le GC, le tas, la zone de méthode et le thread de l'application (jstat, jstack)

    3. vider et analyser les instantanés de vidage de tas (jmap, jhat)

    4. Programme au niveau de la méthode exécutant une analyse des performances pour découvrir les méthodes les plus appelées et les plus longues à exécuter.

    5. Instantané du programme hors ligne : collectez la configuration d'exécution, le vidage des threads, le vidage de la mémoire et d'autres informations du programme pour créer un instantané. Les BUG peuvent être envoyés aux développeurs pour obtenir des commentaires sur les BUG.

    6. Possibilités sans fil fournies par d'autres plugins

    ​ Le plug-in peut être installé manuellement. Après avoir téléchargé le package *.nbm sur le site Web concerné, cliquez sur "Outils" -> "Plug-in" -> "Téléchargé", et spécifiez le chemin du package nbm dans la fenêtre qui s'ouvre. pour l'installer ;

    ​ Cependant, l'installation manuelle n'est pas courante. Utilisez la fonction d'installation automatique de VisualVM pour trouver la plupart des plug-ins dont vous avez besoin. Dans un environnement réseau, cliquez sur "Outils" -> "Plug-ins" -> "Plug-ins disponibles ". Dans la liste contextuelle des plug-ins, vous pouvez l'installer selon vos besoins :

Insérer la description de l'image ici

Après avoir installé le plug-in, sélectionnez un programme qui doit être surveillé dans l'application à gauche pour accéder à la page principale du programme :

Insérer la description de l'image ici

L'onglet Présentation, surveillance, threads, GC, etc. sur le côté droit de VisualVM est similaire à l'introduction de Jconsole ci-dessus et peut être expérimenté par vous-même ;

  1. Générer et parcourir des instantanés de vidage de tas

    Il existe deux manières de générer un instantané de tas de vidage dans VisualVM.

    1. Dans la fenêtre Applications, cliquez avec le bouton droit sur le programme spécifié et sélectionnez Heap Dump

    2. Dans la fenêtre "Applications", double-cliquez sur le programme spécifié, sélectionnez l'onglet "Surveiller" sur la page principale du programme, puis cliquez sur "Dump".

    Une fois le fichier de vidage généré, dans la fenêtre « Application », un sous-nœud [heapdump] sera ajouté sous le programme et le fichier de vidage sera ouvert dans l'interface principale à droite ;

Insérer la description de l'image ici

Si vous souhaitez envoyer ou enregistrer le fichier dump, cliquez sur ce nœud pour sélectionner Enregistrer sous, sinon le fichier dump sera perdu à la fermeture de VisualVM ;

Pour ouvrir un fichier de dump externe qui existe déjà, sélectionnez la fonction « Charger » dans le menu Fichier pour importer le fichier de dump externe ;

  1. Analyser les performances du programme

    Dans l'onglet Profiler, VisualVM fournit une analyse du processeur au niveau de la méthode et une analyse de la mémoire pendant l'exécution du programme. L'analyse du profilage aura certainement un impact plus important sur les performances du programme, cette fonction n'est donc généralement pas utilisée dans les environnements de production ;

    Pour lancer l'analyse, sélectionnez d'abord l'un des boutons "CPU" et "Mémoire", puis passez à la fenêtre de l'application et sélectionnez un programme spécifique. VisualVM enregistrera les méthodes appelées par le CPU pendant cette période :

    1. S'il s'agit d'une analyse CPU, le nombre d'exécutions de chaque méthode et le temps d'exécution seront comptés.
    2. S'il s'agit d'une analyse mémoire, le nombre d'objets associés à chaque méthode et l'espace mémoire occupé par ces objets seront comptés.
    3. Une fois l'analyse terminée, cliquez sur « Stop » pour mettre fin à la surveillance.
  2. Suivi dynamique des journaux BTrace

    BTrace est un plug-in VisualVM « intéressant » qui peut également fonctionner indépendamment ;

    La fonction consiste à ajouter dynamiquement du code de débogage qui n'existe pas via la technologie Hotswap de la machine virtuelle Hotspot sans arrêter l'exécution du programme cible ;

    Cette fonction est très utile pour les applications de production réelles : lorsque vous rencontrez un problème de programme, vous devez vérifier les informations sur le résultat de l'exécution des codes clés, mais si aucun journal n'est ajouté pendant le développement, vous devez arrêter le service et ajouter le journal. résoudre le problème ; ce sera très ennuyeux lorsque l'environnement de production ne peut pas être arrêté à volonté, ce qui entraînera un dépannage.

    Après avoir installé le plug-in BTrace, dans la fenêtre de l'application, cliquez avec le bouton droit sur le programme spécifié et sélectionnez « Trace Application... » pour accéder au panneau BTrace ;

    Il existe de nombreuses autres utilisations de BTrace. L'impression des piles d'appels, des paramètres et des valeurs de retour des méthodes ne sont que des applications de base. Il existe de nombreux exemples sur son site Web pour surveiller les performances, localiser les fuites de connexion, les fuites de mémoire et résoudre les problèmes de concurrence multi-thread. Ceux qui sont intéressés peuvent consulter les sites Web correspondants ;

    Lien du paramètre BTrace : https://www.jianshu.com/p/93e94b724476
    Cliquez sur le programme spécifié, sélectionnez l'onglet "Moniteur" sur la page principale du programme, puis cliquez sur "Heap Dump".

    Une fois le fichier de vidage généré, dans la fenêtre « Application », un sous-nœud [heapdump] sera ajouté sous le programme et le fichier de vidage sera ouvert dans l'interface principale à droite ;

    [Les images de liens externes sont en cours de transfert...(img-KdwF4SnW-1678267817768)]

    Si vous souhaitez envoyer ou enregistrer le fichier dump, cliquez sur ce nœud pour sélectionner Enregistrer sous, sinon le fichier dump sera perdu à la fermeture de VisualVM ;

    Pour ouvrir un fichier de dump externe qui existe déjà, sélectionnez la fonction « Charger » dans le menu Fichier pour importer le fichier de dump externe ;

  3. Analyser les performances du programme

    Dans l'onglet Profiler, VisualVM fournit une analyse du processeur au niveau de la méthode et une analyse de la mémoire pendant l'exécution du programme. L'analyse du profilage aura certainement un impact plus important sur les performances du programme, cette fonction n'est donc généralement pas utilisée dans les environnements de production ;

    Pour lancer l'analyse, sélectionnez d'abord l'un des boutons "CPU" et "Mémoire", puis passez à la fenêtre de l'application et sélectionnez un programme spécifique. VisualVM enregistrera les méthodes appelées par le CPU pendant cette période :

    1. S'il s'agit d'une analyse CPU, le nombre d'exécutions de chaque méthode et le temps d'exécution seront comptés.
    2. S'il s'agit d'une analyse mémoire, le nombre d'objets associés à chaque méthode et l'espace mémoire occupé par ces objets seront comptés.
    3. Une fois l'analyse terminée, cliquez sur « Stop » pour mettre fin à la surveillance.
  4. Suivi dynamique des journaux BTrace

    BTrace est un plug-in VisualVM « intéressant » qui peut également fonctionner indépendamment ;

    La fonction consiste à ajouter dynamiquement du code de débogage qui n'existe pas via la technologie Hotswap de la machine virtuelle Hotspot sans arrêter l'exécution du programme cible ;

    Cette fonction est très utile pour les applications de production réelles : lorsque vous rencontrez un problème de programme, vous devez vérifier les informations sur le résultat de l'exécution des codes clés, mais si aucun journal n'est ajouté pendant le développement, vous devez arrêter le service et ajouter le journal. résoudre le problème ; ce sera très ennuyeux lorsque l'environnement de production ne peut pas être arrêté à volonté, ce qui entraînera un dépannage.

    Après avoir installé le plug-in BTrace, dans la fenêtre de l'application, cliquez avec le bouton droit sur le programme spécifié et sélectionnez « Trace Application... » pour accéder au panneau BTrace ;

    Il existe de nombreuses autres utilisations de BTrace. L'impression des piles d'appels, des paramètres et des valeurs de retour des méthodes ne sont que des applications de base. Il existe de nombreux exemples sur son site Web pour surveiller les performances, localiser les fuites de connexion, les fuites de mémoire et résoudre les problèmes de concurrence multi-thread. Ceux qui sont intéressés peuvent consulter les sites Web correspondants ;

    BTrace utilise le lien de paramètre : https://www.jianshu.com/p/93e94b724476

Acho que você gosta

Origin blog.csdn.net/weixin_40709965/article/details/129407977
Recomendado
Clasificación