深入了解JAVA虚拟机(一)关于JAVA虚拟机的运行时数据区域

运行时数据区域

Java虚拟机在执行java程序的过程中会把它管理的内存区域划分为若干个不同的数据区域。这些区域都有各自的用途以及其生命周期。有的区域随着虚拟机进程的启动而启动,有的区域则依赖用户线程的启动和结束而建立和销毁。根据JVM规范,java虚拟机所管理的内存将会包括以下区域 :
在这里插入图片描述

堆(Heap)

堆是JVM内存占用最大,管理最复杂的一个区域。其主要的用途就是存放对象实例。 从内存回收的角度来看,由于现在主流的垃圾收集器都采用分代收集算法,所以Java堆还可以细分为新生代(Young Generation)和老年代 (Old Generation).从内存分配的角度来看,线程共享的堆内存区域中可以划分出多个线程私有的缓冲区,进一步划分的目的是为了更好地回收内存。

  • HotSpot VM 在jdk1.7以后将字符串常量池从永久代中剥离出来,存放在堆内存中。
  • 如果在堆内存中没有足够的内存完成实例分配,并且堆也无法在拓展时,将会抛出OutOfMemoryError异常。

方法区(MethodArea)

方法区和堆一样,是线程共享的内存区域。它用来存储被虚拟机加载的类信息(版本,字段,方法,接口等描述信息),常量池,即时编译器编译以后的代码等数据。对于习惯在HotSpot VM上开发,部署程序的开发者来说,很多人都更愿意把方法区称为“永久代”(Permanent Generation)。本质上两者并不等价,仅仅是因为HopSpot使用永久代来实现方法区而已,这样HotSpot VM的垃圾回收器就可以像管理堆内存一样管理这部分内存。

  • 常量池是方法区的一部分,用于存储编译期间生成的各种字面量和符号引用。
  • 在jdk 1.7以后,永久代被移除。将类的元数据放在本地内存中,将常量池和静态变量放在堆内存中。
  • 本地内存 并不是虚拟机运行时数据区的一部分,不会受到Java堆内存大小的限制。
  • 根据Java虚拟机的规范,当方法区无法满足内存分配需求时,将会抛出OutOfMemoryError异常。

虚拟机栈(JVM Stacks)

虚拟机栈是线程隔离的。它的生命周期和线程相同。虚拟机栈描述的是Java方法执行的内存模型。每个方法在执行时都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。当前正在执行的方法永远在栈顶。

  • 局部变量表存放了编译器可知的各种基本数据类型和对象引用。
  • 如果线程请求时栈深度大于虚拟机所允许的深度,将会抛出StackOverFlowError异常,如果虚拟机栈可以动态拓展(大部分的虚拟机栈都可以动态拓展),如果申请时无法申请到足够的内存,就会抛出OutOfMemoryError。

本地方法栈(NativeMethodStack)

本地方法栈和虚拟机栈发挥的功能是非常相似的,差别仅仅在于虚拟机栈为虚拟机执行Java方法(也就是Java字节码)服务,本地方法栈则为虚拟机使用到的Native方法服务。在虚拟机规范中对本地方法栈的实现方式并无强制规定,所以具体的虚拟机可以自由地实现它。甚至有的虚拟机(HotSpot VM)直接将两者合二为一.

程序计数器(Program Counter Register)

程序计数器是线程隔离的,可以看作是当前线程所执行的字节码文件(class)的行号指示器。只占用很少的内存空间。虚拟机通过程序计数器选取下一条指令,分支,循环,跳转,异常处理等功能。

  • 程序计数器是唯一一个Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值