JVM学习(一):JVM运行时数据区域

1、JVM运行时内存区域划分

 

2、各区域功能介绍

(1)程序计数器:线程私有内存区域,由于多线程是上下文切换运行,为了使线程切换后能恢复到正确的执行位置,每个线程都有一个独立的程序计数器,当线程执行的是Java方法时,程序计数器记录的是正在执行的虚拟机字节码指令的地址。此区域是JVM中唯一一个不会出现OOM情况的区域。

 

(2)虚拟机栈:线程私有内存区域,生命周期与线程相同,描述的是Java方法执行的内存模型———每个方法在执行的时候都会创建一个栈帧用于存储局部变量表(存放对象的引用)操作数栈动态链接返回地址等,因为采用了先进后出的数据结构进行方法的调用执行,所以叫做虚拟机栈。此区域可能会抛出StackOverflowError异常和OOM异常。

 

(3)本地方法栈:线程私有内存区域,作用类似虚拟机栈(HotSpot虚拟机将这两个栈合二为一),区别就是一个是为执行Java方法服务,一个是为执行Native方法服务。同虚拟机栈,此区域可能会抛出StackOverflowError异常和OOM异常。

 

(4)堆:线程共享内存区域,在虚拟机启动时创建,此内存区域唯一的作用就是存放(非静态)对象实例。堆是JVM内存回收和分配的主要区域,大小可固定也可扩展,当前主流虚拟机都是可扩展的(通过-Xmx-Xms参数控制)。如果堆中没有内存完成实例分配,并且堆也无法再扩展时,将抛出OOM异常。

 

(5)方法区:线程共享内存区域,用于存储类信息、常量、静态变量、即使编译器编译后的代码(字节码对应的指令)等数据。目前HotSpot虚拟机使用永久代来实现方法区,为的是像Java堆一样方便内存的管理,Java虚拟机规范规定方法区可以不实现垃圾回收,但是方法区不等于永久代,此区域的内存回收主要是针对常量池的回收类型的卸载。当方法区无法满足内存分配需求时,将抛出OOM异常。

 

(6)运行时常量池:该区域是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,另外由于其具备动态性,也可能在非编译期的运行期间存入新的常量,应用比较多的是String类的intern()方法。当常量池中无法再申请到内存时,将抛出OOM异常。

 

3、直接内存

(1)直接内存是JDK1.4之后出现的NIO类引入的一块内存区域,不属于JVM运行时数据区域

(2)在配置虚拟机参数时,会根据实际内存设置-Xmx等参数信息,但经常忽略直接内存,使得各个内存区域总和大于物理内存限制,从而导致动态扩展时出现OOM异常。

 

posted on 2019-02-19 22:54  逍遥1989  阅读(131)  评论(0编辑  收藏  举报