Le contenu de cet article concerne la solution à l'exception Java OutOfMemoryError. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Dans la description des spécifications de la machine virtuelle Java, en plus du compteur de programme, des exceptions MOO peuvent se produire dans plusieurs autres zones en cours d'exécution de la mémoire de la machine virtuelle. Ici, nous utilisons du code pour vérifier ce qui est stocké dans chaque zone d'exécution et discutons de la manière de le gérer.
Débordement du tas Java
Le tas Java est utilisé pour stocker les instances d'objets Tant que les objets sont créés en continu, il existe un chemin accessible entre les racines GC et l'objet. pour éviter un mécanisme de récupération de place pour effacer ces objets, une exception de dépassement de mémoire se produira une fois que le nombre d'objets aura atteint la limite maximale de capacité du tas.
Reproduction des exceptions
Le code utilise les paramètres de machine virtuelle suivants :
-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
De cette façon, la taille du tas Java sera limité à 20 Mo et ne peut pas être étendu. Grâce au paramètre -XX:+HeapDumpOnOutOfMemoryError, la machine virtuelle peut vider l'instantané de vidage du tas de mémoire actuel pour analyse lorsqu'une exception de dépassement de mémoire se produit.
Utilisez le code suivant pour vérification :
public class HeapOOM { static class OOMObject { } public static void main(String[] args) { List<OOMObject> list = new ArrayList<OOMObject>(); while (true) { list.add(new OOMObject()); } } }
Résultats en cours d'exécution :
java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid3460.hprof ... Heap dump file created [28199779 bytes in 0.237 secs]
L'exception MOO de la mémoire tas Java est une application pratique Les exceptions courantes de dépassement de mémoire sont souvent suivies de l'invite « Espace de tas Java » lorsqu'elles se produisent.
Pour résoudre l'anomalie dans ce domaine, la méthode générale consiste à utiliser d'abord un outil d'analyse d'image mémoire, tel que MAT, pour confirmer s'il y a une fuite de mémoire ou un débordement de mémoire.
S'il s'agit d'une fuite de mémoire, vous pouvez également utiliser des outils pour afficher la chaîne de référence de l'objet divulgué aux racines GC, et découvrir comment l'objet divulgué est associé aux racines GC et empêche le ramasse-miettes de les recycler automatiquement.
S'il ne s'agit pas d'une fuite de mémoire, en d'autres termes, les objets en mémoire ont vraiment besoin de survivre, alors vous devez vérifier les paramètres du tas de la machine virtuelle et les comparer avec la mémoire physique de la machine pour voir si cela peut être augmenté. Au niveau du code, s'il y a des objets dont le cycle de vie est trop long et que l'état est conservé trop longtemps, essayez de réduire la consommation de mémoire lors de l'exécution du programme.
Étant donné que la pile de machines virtuelles ou la pile de méthodes locales ne sont pas distinguées dans la machine virtuelle HotSpot, pour HotSpot, bien que le paramètre -Xoss existe, dans en fait, elle n'est pas valide. La capacité de la pile est uniquement définie par le paramètre -Xss.
En monothread, le code utilise les paramètres de machine virtuelle suivants :
-Xss128k
Utilisez ce paramètre pour réduire la capacité de la pile, et utilisez le code suivant pour reproduire l'exception :
public class JavaVMStackSOF { private int stackLength = 1; public void stackLeak() { stackLength++; stackLeak(); } public static void main(String[] args) throws Throwable { JavaVMStackSOF oom = new JavaVMStackSOF(); try { oom.stackLeak(); } catch (Throwable e) { System.out.println("stack length:" + oom.stackLength); throw e; } } }
Si vous utilisez les paramètres par défaut de la machine virtuelle, la profondeur de la pile est dans la plupart des cas (car la taille de trame poussée dans la pile par chaque méthode est pas la même chose, donc seulement On peut dire que dans la plupart des cas, il n'y a aucun problème pour atteindre 1000 ~ 2000. Pour les appels de méthode normaux (y compris la récursivité), cette profondeur devrait être tout à fait suffisante.
Cependant, si le dépassement de mémoire est causé par la création d'un trop grand nombre de threads, si vous ne pouvez pas réduire le nombre de threads ou remplacer la machine virtuelle 64 bits, vous ne pouvez échanger plus qu'en réduisant le tas et la pile maximum. capacité du fil.
Débordement de mémoire directe native
La capacité de DirectMemory peut être spécifiée par -XX : MaxDirectMemorySize Si elle n'est pas spécifiée, elle est par défaut la même que la. Tas maximum Java .
Utilisez les paramètres de machine virtuelle suivants :
-Xmx20M -XX:MaxDirectMemorySize=10M
Utilisez le code suivant pour reproduire l'exception :
public class DirectMemoryOOM { private static final int _1MB = 1024 * 1024; public static void main(String[] args) throws Exception { Field unsafeField = Unsafe.class.getDeclaredFields()[0]; unsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) unsafeField.get(null); while (true) { unsafe.allocateMemory(_1MB);//直接申请分配内存 } } }
Une caractéristique évidente du débordement de mémoire provoqué par DirectMemory est qu'aucune exception évidente ne sera visible dans le fichier Heap Dump.
Si vous constatez que le fichier Dump après le MOO est très petit et que NIO est utilisé directement ou indirectement dans le programme, vous pouvez envisager de vérifier si c'est la raison.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!