深入理解JVM -- 内存模型及内存溢出(OOM/Out of Memory)

来源:互联网 发布:mac邮件里面的qq邮箱 编辑:程序博客网 时间:2024/05/22 06:22

JVM内存分为堆(heap)、方法区(method area)、虚拟机栈(vm stack)、本地方法栈(native method stack)、程序计数器。

其中堆、方法区是线程共享;虚拟机栈、本地方法栈和程序计数器是线程独享。

程序计数器

程序技术器记录java程序下一条需要执行的指令, 因为jvm实现线程是共享cpu, 就是在某一时刻,当一个线程占用处理器(对于多核处理器来说是一个内核)时, 另一线程处于等待状态,当线程切换时, 为了保证线程的代码能正确执行,程序计数器必须线程独有。

程序计数器没有内存溢出。

虚拟机栈

虚拟机栈随着线程的建立而建立,线程结束后销毁。一个java线程可能调用多个方法,当方法被调用时,响应度栈帧被压入栈, 栈帧中保存着方法的局部变量、返回地址等信息。

本地方法栈当栈深度大于虚拟机所允许的深度,将抛出StackOverflowError;

栈在扩展过程中,无法申请到足够的内存控件,则抛出OutOfMemoryError:unable to create new native thread


可通过配置 -Xss参数设置栈大小。

本地方法栈

用于管理java本地方法。 sun的hotspot虚拟机将java本地方法栈和虚拟机栈合二为一。

Java的堆保存所有java动态创建的对象信息, 是jvm中内存中最大一块。 

堆内存溢出后, 错误信息如下:

java.lang.OutOfMemoryError: Java heap space

可通过堆参数(-Xmx与-Xms)配置堆大小。建议将-Xms、-xmx设置为同样大小,这样可以避免尹扩展内存而引起的性能问题。

方法区

方法区保存java中类信息和常量信息。

方法区内存溢出时, 错误信息如下:

java.lang.OutOfMemoryError: PermGenspace

 

设置方法区内存大小可以通过: -XX:PermSize/-XX:MaxPermSize

直接内存区

直接内存区是非堆栈所属内存区, 例如NIO类,它使用native方法在堆栈外直接分配内存,并在JVM内部拥有该内存的应用,减少了数据从jvm外到堆的copy过程, 从而提高了效率。

直接内存区内存大小 +  堆栈内存区大小 < 机器总内存大小。
直接内存溢出错误如下:

java.lang.OutOfMemoryError:






0 0
原创粉丝点击