La spécification de la machine virtuelle Java stipule que la mémoire JVM est divisée en plusieurs blocs, tels que le tas, la pile, le compteur de programmes, la zone de méthode, etc. Dans l'implémentation de Hotspot JVM, la mémoire du tas est divisée en trois parties, la nouvelle génération, la vieillesse et la bande persistante. La bande persistante implémente la zone de méthode spécifiée dans la spécification, et différentes parties du modèle de mémoire auront des erreurs d'OutofMemoryerror correspondantes. Ensuite, discutons-y séparément. Je crois que la plupart des développeurs ont rencontré cette erreur, et les raisons de cette erreur sont principalement causées par les raisons suivantes:
La mémoire JVM est trop petite et le programme n'est pas serré, ce qui entraîne trop de déchets.
Il y a plusieurs causes communes d'exceptions d'OutofMemoryError:
Invite d'erreur commune pour cette erreur:
StackOverflowerror
Stack Overflow lance une erreur java.lang.stackoverflowerror. Cela se produit parce que la profondeur de la pile dépasse la profondeur maximale autorisée par la machine virtuelle lorsque la méthode est en cours d'exécution. Cette situation se produit généralement en raison d'erreurs de programme. Par exemple, la rédaction d'une récursivité morte peut provoquer cette situation. Simulons le débordement de la mémoire dans cette situation à travers un morceau de code.
import java.util. *; importer java.lang. *; classe publique oomtest {public void stackOverflowMethod () {stackOverflowMethod (); } public static void main (String ... args) {oomtest oom = new oomtest (); oom.stackoverflowMethod (); }} L'exécution du code ci-dessus lancera l'exception suivante:
Exception dans Thread "Main" java.lang.stackoverflowerror sur oomtest.stackoverflowMethod (oomtest.java:6)
Tas débordement (outofMemoryError: espace de tas java)
Lorsque la mémoire du tas déborde, la machine virtuelle lance java.lang.outofMemoryError: Java Heap Space. Lorsque cela se produit, nous devons l'analyser spécifiquement en fonction du fichier de vidage généré lorsque la mémoire déborde (-xx: + heapdumponoutofMemoryErrorjvm Le paramètre de démarrage doit être ajouté). Lorsqu'un tel problème se produit, il peut s'agir d'une fuite de mémoire ou d'un débordement de mémoire.
Si la mémoire fuit, nous devons découvrir comment l'objet divulgué est référencé par GC Root, puis analyser la cause de la fuite à travers la chaîne de référence.
S'il y a un problème de débordement de mémoire, c'est souvent parce que le programme a besoin de plus de mémoire que la mémoire que nous configurons pour la machine virtuelle. Dans ce cas, nous pouvons utiliser le -xmx pour résoudre ce problème.
Ci-dessous, nous démontrons le débordement de cette situation à travers le code suivant:
import java.util. *; importer java.lang. *; classe publique oomtest {public static void main (String ... args) {list <byte []> buffer = new ArrayList <Byte []> (); Buffer.Add (nouveau octet [10 * 1024 * 1024]); }} Nous exécutons le code ci-dessus via la commande suivante:
Java -Verbose: GC -xmn10m -xms20m -xmx20m -xx: + printgc oomtest
Le programme entre dans les informations suivantes:
[GC 1180K-> 366K (19456K), 0,0037311 SECS] [GC complet 366K-> 330K (19456K), 0,0098740 Secs] [GC complet 330K-> 292K (19456K), 0,0090244 Secs] Exception dans le thread "Main" Java.lang.outofmmeror: Java Space "Main" java.lang.Lang.outofmmoror Oomtest.main (oomtest.java:7)
D'après les résultats en cours d'exécution, nous pouvons voir que le JVM a effectué un GC mineur une fois et deux fois GC majeur. D'après la sortie du major GC, on peut voir que le taux d'utilisation de l'ancienne zone après GC est de 134k, et le réseau d'octets est de 10 m, ce qui s'additionne plus grand que l'espace de l'ancienne génération, donc une exception est lancée. Si -xms21m et -xmx21m sont ajustés, alors l'opération GC ne sera pas déclenchée et il n'y aura pas d'exception.
Grâce à l'expérience ci-dessus, une conclusion a été vérifiée du côté: lorsque l'objet est plus grand que la mémoire restante de la nouvelle génération, elle sera placée directement dans la vieillesse. Lorsque la mémoire restante de la vieillesse est toujours incapable d'être déposée, la collecte des ordures sera déclenchée. S'il ne peut toujours pas être déposé après la collection, une exception de débordement de mémoire sera lancée.
Permgen Space
Nous savons que Hotspot JVM implémente la zone de méthode dans la spécification de la machine virtuelle Java à travers des bandes persistantes, et le pool constant d'exécution est stocké dans la zone de méthode. Par conséquent, le débordement persistant de la bande peut être le débordement de pool constant d'exécution, ou les objets de classe enregistrés dans la zone de la méthode ne sont pas recyclés dans le temps ou la mémoire occupée par les informations de classe dépasse notre configuration. Lorsque la bande de persistance déborde, java.lang.outofMemoryError: l'espace permgen est lancé.
Je peux rencontrer ce problème dans les scénarios suivants lorsque vous travaillez.
Lorsque vous utilisez le déploiement à chaud de certains serveurs d'applications, nous rencontrerons plusieurs fois le déploiement à chaud et constaterons que la mémoire déborde. En effet, après chaque déploiement à chaud, la classe d'origine n'a pas été désinstallée.
Si l'application elle-même est plus grande et implique plus de bibliothèques de classe, ce problème peut également se produire lorsque la mémoire que nous allouons à la bande persistante (définie par -xx: permsize et -xx: maxpermSize) est relativement petite.
Certains cadres tiers, tels que Spring et Hibernate, implémentent tous certaines fonctions améliorées via la technologie de génération Bytecode (telle que CGLIB), qui peut nécessiter une zone de méthode plus grande pour stocker des fichiers de classe générés dynamiquement.
Nous savons que les constantes de cordes en Java sont placées dans une piscine constante. Lorsque la méthode String.intern () est exécutée, elle vérifiera si des objets égaux à cette chaîne sont stockés dans le pool constant. S'il existe, renvoyez directement une référence à l'objet dans le pool constant. S'il n'existe pas, ajoutez cette chaîne au pool constant d'abord, puis renvoyez la référence à la chaîne. Ensuite, nous pouvons simuler le débordement de la zone constante pendant l'exécution via la méthode String.intern. Simulons cette situation à travers le code suivant:
import java.util. *; importer java.lang. *; classe publique oomtest {public static void main (String ... args) {list <string> list = new ArrayList <string> (); while (true) {list.add (uuid.randomuuid (). toString (). Intern ()); }}}Nous exécutons le code ci-dessus via la commande suivante:
Java -Verbose: GC -xmn5m -xms10m -xmx10m -xx: maxpermSize = 1m -xx: + printgc oomtest
L'entrée après l'exécution est indiquée dans la figure ci-dessous:
Exception dans Thread "Main" java.lang.outofMemoryError: Permgen Space at java.lang.string.intern (méthode native) à oomtest.main (oomtest.java:8)
Grâce au code ci-dessus, nous avons simulé avec succès le débordement de pool constant pendant l'exécution. De l'espace Permgen dans la sortie, nous pouvons voir que la bande persistante déborde en effet, ce qui vérifie également l'affirmation selon laquelle le hotspot JVM implémente la zone de méthode à travers la bande persistante comme mentionné précédemment.
OutOfMemoryError: Impossible de créer un fil natif
Enfin, jetons un coup d'œil à l'erreur java.lang.outofMemoryError: Impossible de créer un fil Natvie. Lorsque cela se produit, il est généralement causé par les deux situations suivantes:
Le nombre de threads créés par le programme dépasse la limite du système d'exploitation. Pour les systèmes Linux, nous pouvons voir cette limitation via Ulimit -u.
La mémoire allouée à la machine virtuelle est trop grande, ce qui entraîne trop peu de mémoire native requise lors de la création de threads. Nous savons tous que le système d'exploitation a une limite sur la mémoire de chaque processus. Lors du démarrage de JVM, il équivaut à démarrer un processus. Si l'un de nos processus occupe 4 g de mémoire, alors la mémoire restante calculée via la formule suivante est la mémoire qui peut être utilisée lors de la construction d'une pile de threads. Mémoire disponible totale pour la pile de threads = 4G- (valeur de -xmx) - (- xx: valeur de maxpermSize) - La mémoire occupée par le compteur de programme est montrée par la formule ci-dessus que plus les valeurs de -xmx et maxpermsize sont grandes, plus l'espace disponible pour la pile de threads. Lorsque la capacité de pile configurée par le paramètre -XSS reste inchangée, plus le nombre de threads peut être créé. Par conséquent, s'il est impossible de créer un thread natif en raison de cette situation, nous augmentons la mémoire totale occupée par le processus ou réduisons -xmx ou -xss pour atteindre le but de créer plus de threads.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.