Java内存区域与各区域OOM

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6534990.html 

    JVM的组成在上一篇博文已经介绍了,现在我们专门深入Java运行时数据区。

   

    1:程序计数器

     当前线程执行的字节码文件的行号指示器,用于线程切换之后恢复上次执行时的位置继续执行。各个线程之间的计数器互不影响,“线程私有”。

     这是唯一一个在JVM中没有OOM异常的区域。

    2:虚拟机栈

     这也是线程私有的,保留了当前线程的方法栈帧:每个方法执行时会创建栈帧,用于存储局部变量、操作数、方法出口等。每个方法从调用到执行完成就对应这一个栈帧在虚拟机栈中入栈到出栈的过程。

     这个区域有两种异常:方法栈的深度大于虚拟机所允许的深度就会抛出StackOverflowError异常;栈的大小扩展时如果无法获得足够的内存就会抛出OOM异常。

    3:本地方法栈

     为本地的Native方法服务,功能与虚拟机栈类似,也会由于深度问题或扩展时内存不够而抛出StackOverflowError或OOM异常。

    4:Java堆

     被所有线程共享的一片区域,所有对象实例以及数组都在堆上分配内存。可以通过:-Xmx、-Xmx设置堆的大小上下限。我们习惯上把堆划分为新生代和老年代,具体划分在GC机制的博文详述。

     当堆的内存不足时,抛出OOM异常。

    5:方法区

     被各个线程共享,存储被虚拟机加载的类的信息、常量、静态变量等,为了与堆进行区分,又有“非堆”的别名。

     由于在HotSpot虚拟机中把GC机制扩展到了方法区,使得垃圾收集器可以像Java堆那样管理这部分内存,故方法区又叫“永久代”。这部分区域的垃圾回收为废弃常量和无用的类。废弃常量:常量池中没有被任何对象引用的常量值。无用的类:无任何对象实例、类加载器已被回收、Class对象没有被引用的类文件。

     当方法区内存达到-XX:MaxPermSize上限时抛出OOM异常。

       5.1:常量池

             存放编译器生成的各种字面量、符号引用。

    

    拓展:直接内存

    直接内存是本机的内存,不收Java堆大小的限制。但是当服务器管理员配置虚拟机参数时,如果各个内存区域的总和大于本机物理内存限制,就会出现OOM异常。

原文地址:https://www.cnblogs.com/ygj0930/p/6534990.html