Le tas Java est utilisé pour stocker les instances d'objets. Par conséquent, si nous créons en continu des objets et nous assurons qu'il existe un chemin accessible entre GC Root et l'objet créé pour éviter que l'objet ne soit collecté, alors lorsque trop d'objets seront créés, il provoquera une mémoire de tas insuffisante, ce qui augmentera une exception d'OutofMemoryError.
/ ** * @author xiongyongshun * vm args: java -xms10m -xmx10m -xx: + heapdumponoutofMemoryError * / public class overofMemoryErrortest {public static void main (String [] args) {list <inter> list = new ArrayList <> (); int i = 0; while (true) {list.add (i ++); }}}Ce qui précède est un code qui soulève une exception OutOfMemoryError. Nous pouvons voir qu'il empêche l'objet d'être collecté des ordures en créant et en enregistrant constamment l'objet dans la liste. Par conséquent, lorsqu'il y a trop d'objets, la mémoire du tas débordera.
Grâce à Java -XMS10M -XMX10M -XX: + HeapDumponoutofMemoryError, nous définissons la mémoire du tas sur 10 mégaoctets et utilisons le paramètre -xx: + HeapDumponoutOfMemoryError pour que JVM imprime le Snaph Snapshot actuel lorsqu'une exception OutoFmemoryerror pour une analyse suivante.
Après avoir compilé et exécuté le code ci-dessus, la sortie suivante sera:
>>> java -xms10m -xmx10m -xx: + heapdumponoutofMemoryError com.test.outofmemoryerrorst 16-10-02 23: 35java.lang.outofmemoryerror: Java tas spacedumping tas to Java_pid1810.hprof ... le fichier de vidage du huile créé par le fichier de vidage [142861. 0,125 secondes] Exception dans le thread "Main" java.lang.outofMemoryError: Java Heaap Space à java.util.arrays.copyof (arrays.java:3210) à java.util.arrays.copyof (arrays.java:3181) à java.util.arraylist. java.util.arraylist.enSureExplicitCapacity (arrayList.java:235) sur java.util.arraylist.enurecapacityinternal (arraylist.java:227) à java.util.arraylist.add (arraylist.java:458) com.test.outofMemoryErrortest.main (overofmemoryerrorst.java:15)
Java stackOverflowerror
Nous savons qu'il existe une zone de mémoire appelée la pile de machines virtuelles dans la zone de données d'exécution du JVM. La fonction de ce domaine est: chaque méthode créera une trame de pile lors de son exécution, qui est utilisée pour stocker des informations telles que les tables variables locales, les piles d'opérande, les sorties de méthode, etc.
Par conséquent, nous pouvons créer un appel récursif infiniment récursif. Lorsque la profondeur récursive est trop grande, l'espace de pile sera épuisé, ce qui mènera à une exception Stackoverflowerror.
Voici le code spécifique:
/ ** * @author xiongyongshun * vm args: java -xss64k * / public class outofMemoryErrOrest {public static void main (String [] args) {stackOutofMemoryError (1); } public static void stackoutofMemoryError (int de profondeur) {de profondeur ++; stackOutofMemoryError (profondeur); }}Après avoir compilé et exécuté le code ci-dessus, les informations d'exception suivantes seront sorties:
Exception dans Thread "Main" java.lang.stackoverflowerror sur com.test.outofMemoryErrortest.StackoutofMemoryError (outofMemoryErrortest.java:27)
Débordement de mémoire dans la zone de la méthode
Notez que parce que JDK8 a supprimé la génération permanente et l'a remplacée par Metaspace, dans JDK8, aucun des deux exemples suivants ne provoquera java.lang.outofMemoryError: Permgen Space Exception.
Les débordements de piscine constants pendant l'exécution
Dans Java 1.6 et les versions précédentes de Hotspot JVM, il existe un concept de génération permanente, c'est-à-dire que le mécanisme de collecte de génération de GC est étendu à la zone de méthode. Dans la zone de la méthode, une partie de la mémoire est utilisée pour stocker des pools constants. Par conséquent, s'il y a trop de constantes dans le code, la mémoire du pool constant sera épuisée, entraînant un débordement de mémoire. Alors, comment ajouter un grand nombre de constantes à la piscine constante? À l'heure actuelle, vous devez compter sur la méthode string.intern (). La fonction de la méthode string.intern () est: si la valeur de cette chaîne existe déjà dans le pool constant, cette méthode renvoie la référence à la chaîne correspondante dans le pool constant; Sinon, ajoutez la valeur contenue dans cette chaîne au pool constant et renvoyez la référence à cet objet de chaîne. Dans JDK 1.6 et les versions précédentes, le pool constant est alloué dans la génération permanente. Par conséquent, nous pouvons indirectement limiter la taille du pool constant en définissant les paramètres "-xx: permsize" et "-xx: maxpermSize".
Notez que la distribution de mémoire de la méthode String.intern () mentionnée ci-dessus et que le pool constant est uniquement pour JDK 1.6 et les versions précédentes. Dans JDK 1.7 ou plus, la disposition de la mémoire est légèrement différente car le concept de génération permanente est supprimé.
Ce qui suit est un exemple de code pour implémenter un débordement de mémoire de pools constants:
/ ** * @author xiongyongshun * vm args: -xx: permsize = 10m -xx: maxPermSize = 10m * / public class runtimeConstantPooloomTest {public static void main (string [] args) {list <string> list = new ArrayList <string> (); int i = 0; while (true) {list.add (string.valueof (i ++). Intern ()); }}}Nous voyons que dans cet exemple, il utilise précisément la méthode String.intern () pour ajouter un grand nombre de constantes de chaîne au pool constant, ce qui conduit au débordement de la mémoire du pool constant.
Nous compilons et exécutons le code ci-dessus via JDK1.6, et la sortie suivante sera:
Exception dans Thread "Main" java.lang.outofMemoryError: Permgen Space at java.lang.string.intern (méthode native) sur com.test.runtimeconstantpooloomtest.main (runtimeConstantPooloomTest.java:16)
Il convient de noter que si le code ci-dessus est compilé et exécuté via JDK1.8, il y aura l'avertissement suivant et aucune exception ne sera générée:
>>> java -xx: permsize = 10m -xx: maxpermSize = 10m com.test.runtimeConstantPooloomTest 16-10-03 0: 23java hotspot (tm) 64 bits serveur VM Avertissement: ignorer l'option permsize = 10m; La prise en charge a été supprimée dans 8.0 Java Hotspot (TM) 64 bits Server VM Avertissement: Ignorer l'option maxpermSize = 10m; Le support a été supprimé en 8.0
Débordement de mémoire dans la zone de la méthode
La fonction de la zone de méthode consiste à stocker les informations pertinentes de la classe, telles que les noms de classe, les modificateurs d'accès de classe, les descriptions de champ, les descriptions de méthode, etc. Par conséquent, si la zone de méthode est trop petite et que trop de classes sont chargées, le débordement de la mémoire de la zone de méthode.
// vm args: -xx: permSize = 10m -xx: maxPermSize = 10MPublic class MethodAreAoomTest {public static void main (String [] args) {while (true) {Enhancer Enhancer = new Enhancer (); Enhancer.SetSuperclass (méthodyAreAoomTest.class); Enhancer.SetUseCache (false); Enhancer.SetCallback (new MethodInterceptor () {public Object Intercept (Object O, méthode Method, objet [] objets, méthodyProxy methodproxy) lève le throwsable {return methodproxy.invokeuper (o, objets);}}); Enhancer.Create (); }}}Dans le code ci-dessus, nous utilisons CGLIB pour générer dynamiquement un grand nombre de classes. Dans JDK6, l'exécution du code ci-dessus générera une exception OutOfMemoryError: Permgen Space:
/System/library/frameworks/javavm.framework/versions/1.6/home/bin/java -jar -xx: permsize = 10m -xx: maxpermSize = 10m cible / test-1.0-snapshot.jar
Le résultat de sortie est le suivant:
Causé par: java.lang.outofMemoryError: Permgen Space à java.lang.classloader.defineclass1 (méthode native) sur java.lang.classloader.defineclasscond (Classloader.java:637) à java.lang.classer.
Metaspace Memory Overflow
Dans la section de débordement de mémoire de débordement de mémoire dans le domaine de la méthode, nous avons mentionné que JDK8 n'a aucun concept de génération permanente, donc ces deux exemples n'ont pas atteint l'effet attendu sous JDK8. Donc, dans JDK8, y a-t-il des erreurs comme le débordement de la mémoire dans la zone de méthode? Bien sûr, certains. Dans JDK8, la zone Metaspace est utilisée pour stocker des informations liées à la classe, donc lorsque Metaspace est insuffisant, une exception Java.lang.outofMemoryError: Metaspace sera lancée.
Prenons l'exemple mentionné ci-dessus comme exemple:
// vm args: -xx: maxMetAspaceSize = 10Mpublic class MethodAreAoomTest {public static void main (String [] args) {while (true) {Enhancer Enhancer = new Enhancer (); Enhancer.SetSuperclass (méthodyAreAoomTest.class); Enhancer.SetUseCache (false); Enhancer.SetCallback (new MethodInterceptor () {public Object Intercept (Object O, méthode Method, objet [] objets, méthodyProxy methodproxy) lève le throwsable {return methodproxy.invokeuper (o, objets);}}); Enhancer.Create (); }}}La partie de code de cet exemple n'a pas été modifiée. La seule différence est que nous devons utiliser JDK8 pour exécuter ce code et définir le paramètre -xx: maxMetAspaceSize = 10m. Ce paramètre indique au JVM que la taille maximale de Metaspace est de 10 m.
Ensuite, nous utilisons JDK8 pour compiler et exécuter cet exemple, et sortit l'exception suivante:
>>> java -jar -xx: maxMetaspaceSize = 10m Target / test-1.0-snapshot.jarexception dans le thread "Main" java.lang.outofMemoryError: Metaspace at net.sf.cglib.core.abstracclassgenerator. net.sf.cglib.proxy.enhancer.generate (Enhancer.java:492) sur net.sf.cglib.core.abstractclassgenerator $ classloaderdata.get (abstractClassGenerator.java:114) net.sf.cglib.core.abstractclassgenerator.create (abstractClassGenerator.java:291) sur net.sf.cglib.proxy.enhancer.createhelper (Enhancer.java:480) sur net.sf.cglib.proxy.enhancer. com.test.methodareaoomtest.main (MethodAreAoomTest.java:22)
Résumer
Ce qui précède est tout au sujet des exceptions de débordement de mémoire et des exemples de code dans cet article, j'espère que cela sera utile à tout le monde. Les amis intéressés peuvent continuer à se référer à d'autres sujets connexes sur ce site. S'il y a des lacunes, veuillez laisser un message pour le signaler. Merci vos amis pour votre soutien pour ce site!