Maison >Java >javaDidacticiel >Explication détaillée de l'objectif de chaque zone de la JVM et exemples de code d'exceptions potentielles

Explication détaillée de l'objectif de chaque zone de la JVM et exemples de code d'exceptions potentielles

黄舟
黄舟original
2017-03-20 10:56:192042parcourir

Program Counter

est utilisé par l'interpréteur de bytecode pour sélectionner les instructions de bytecode qui doivent être exécutées. Chaque thread possède un compteur de programme indépendant et les threads ne s'influencent pas mutuellement. Si le thread exécute une méthode Java, ce compteur enregistre l'adresse mémoire de l'instruction de bytecode de la machine virtuelle en cours d'exécution s'il exécute une méthode native ; Le compteur est indéfini. Cette zone est la seule zone de la spécification JVM où le MOO n'existe pas

Pile de machines virtuelles (espace variable local)

stocke divers types de données de base connus du compilateur (booléen, octet, char , short, int, float, long, double), application objet (référence). 64 bits doubles et longs occupent 2 emplacements. L'espace mémoire peut être déterminé lors de la compilation. Lors de la saisie d'une méthode, l'espace variable local qui doit être alloué par cette méthode est complètement déterminé via -Xss

Exception :

StackOverflowError La profondeur de la pile est supérieure à la profondeur autorisée par la machine virtuelle

MOO Si la pile de la machine virtuelle peut être étendue dynamiquement (la plupart des machines virtuelles Java actuelles peuvent être étendues dynamiquement, mais la spécification de la machine virtuelle Java permet également pile de machines virtuelles de longueur fixe), si l'extension ne peut pas demander suffisamment de mémoire

Dans un seul thread, si le cadre de pile est trop grand ou si la capacité de la pile de machine virtuelle est trop petite, lorsque la mémoire ne peut pas être allouée , la machine virtuelle lance Ce sont tous des StackOverflowError

/**
* VM Args:-Xss128k
* 
* stack length:2402 Exception in thread "main" java.lang.StackOverflowError
*/
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 le test n'est pas limité à un seul thread, des exceptions de dépassement de mémoire peuvent être générées en établissant continuellement des threads. Cependant, l'exception de débordement de mémoire générée de cette manière n'a aucun lien avec le fait que l'espace occupé soit suffisamment grand. Pour être précis, dans ce cas, plus la mémoire allouée à la pile de chaque thread est grande, plus il est facile de générer une exception de débordement de mémoire. .

Parce que la mémoire allouée par le système d'exploitation à chaque processus est limitée, par exemple, une fenêtre 32 bits est limitée à 2 Go. Ce test se fait en créant un grand nombre de threads. Chaque thread occupe la mémoire de la pile et alloue une grande quantité de mémoire, ce qui fait que le système ne dispose pas de suffisamment de mémoire. Pour qu'elle ne puisse pas se développer automatiquement

/**
 * VM Args:-Xss2M (这时候不妨设大些)
 *
 * java.lang.OutOfMemoryError:unable to create new native thread
 */
public class JavaVMStackOOM {

       private void dontStop() {
              while (true) {
              }
       }

       public void stackLeakByThread() {
              while (true) {
                     Thread thread = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                   dontStop();
                            }
                     });
                     thread.start();
              }
       }

       public static void main(String[] args) throws Throwable {
              JavaVMStackOOM oom = new JavaVMStackOOM();
              oom.stackLeakByThread();
       }
}
La pile de méthodes locales

est similaire à la pile de machines virtuelles, sauf que l'une est la machine virtuelle exécutant les méthodes Java et l'autre exécutant Native méthodes

Statut d'exception :

StackOverflowError La profondeur de la pile est supérieure à la profondeur autorisée par la machine virtuelle

OOM

Tas Java

Une zone mémoire partagée par les threads, du point de vue du recyclage de la mémoire Il semble que l'algorithme de collecte générationnelle soit essentiellement utilisé, il est donc divisé en nouvelle génération et en ancienne génération. Pour être plus détaillé, il peut être divisé en espace Eden, espace From Survivor, To Survivor, etc. -Xmx -Xms contrôle la taille de l'espace du tas

Exception :

1.OOM Lorsque le tas ne peut pas être étendu

/**
 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 * 
 * java.lang.OutOfMemoryError: Java heap space
 */
public class HeapOOM {

    static class OOMObject {
    }

    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<OOMObject>();

        while (true) {
            list.add(new OOMObject());
        }
    }
}
Zone de méthode

Partagée entre les fils. Stocke les données telles que les informations de classe, les constantes, les variables statiques, le code compilé par l'éditeur instantané, etc. qui ont été chargés par la machine virtuelle. Cela peut être appelé la génération immortelle dans la machine virtuelle HotSpot.

Les constantes d'exécution font partie de la zone de méthode dans la version 1.6 et avant (String.intern() ajoute dynamiquement le pool de constantes) -XX:MaxPermSize contrôle la taille. Dans JDK1.7 et versions ultérieures, un morceau de mémoire est ouvert dans le tas Java

Situation d'exception :

OOM

/**
* 需要在JDK1.6上才能复现,JDK1.7及之后版本的JVM已经将运行时常量池从方法区中移了出来,在Java 堆(Heap)中开辟了一块区域存放运行时常量池。
* 在JDK1.7上运行的效果则会一直执行,直到堆内存使用完毕
* VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M 
*
* java.lang.OutOfMemoryError:PermGen space
*/
public class RuntimeConstantPoolOOM {

public static void main(String[] args) {
    // 使用List保持着常量池引用,避免Full GC回收常量池行为
    List<String> list = new ArrayList<String>();
    // 10MB的PermSize在integer范围内足够产生OOM了
    int i = 0;
    while (true) {
        list.add(String.valueOf(i++).intern());
    }
}
}
/**
* VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
* java.lang.OutOfMemoryError:PermGen space
* 一直创建动态类
*/
public class JavaMethodAreaOOM {

public static void main(String[] args) {
    while (true) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(OOMObject.class);
        enhancer.setUseCache(false);
        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                return proxy.invokeSuper(obj, args);
            }
        });
        enhancer.create();
    }
}

static class OOMObject {

}
}
Mémoire directe (pas partie de la zone de données lorsque la machine virtuelle est en cours d'exécution)

NIO peut utiliser la bibliothèque de fonctions natives pour allouer directement de la mémoire externe, puis opérer via l'objet DirectByteBuffer stocké dans la paire Java comme référence à cela mémoire. Limité par la mémoire physique de la machine, il peut être spécifié via -XX:MaxDirectMemorySize S'il n'est pas spécifié, la valeur par défaut est la même que le maximum du tas Java (-Xmx)

Exception :

1. .MOO

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn