jvm运行时数据区

原创
2014/01/22 01:48
阅读数 392

javase7 specific中描述的运行时数据区:

jvm在执行程序的过程中定义了不同的数据区,有一些数据区是与jvm生命周期一致的,我们就称其为共享区,有一些则是与线程生命周期一致的,哪jvm到底定义了哪些运行时数据区呢?如图所示,


依次来介绍一下它们:

  • 程序计数器(PC)寄存器:

        线程私有,如果当前线程正在执行非本地(Native)方法,则PC指向下一条要执行的指令,若正在执行的方法是本地(Native)方法, 则PC的值未知。

  • Java虚拟机栈(Jvm Stack):

        线程私有,jvm创建线程的同时,就会为该线程创建一个,栈里面有很多栈帧(Stack Frame), 每调用一个方法就会push一个栈帧到栈里,一旦方法返回就pop当前帧,栈帧里就存放着局部变量,操作数,字节码指令,可通过-Xss[?]设置栈大小,栈也可以动态扩展,其内存不必连续,java虚拟机栈在运行期间有可能抛出2种异常:

        1. StackOverflowError: 线程请求的栈容量大于允许范围内栈大小时;

        2. OutOfMemoryError: 当栈动态扩展时,没有足够的内存可用;或者当初始化一个新线程的栈时没有足够内存可用。

  • 堆(Heap):

        线程共享,堆保存了运行时的类实例对象和数组对象,随jvm实例启动而被创建。堆虽然是共享的,但堆中也有可能会分配线程私有的分配缓冲区(Thread Local Allocatioin Buffer, TLAB),但存储的仍然是对象实例,只是为了更快的分配和回收内存堆是GC主要的回收区,其内存不必连续,会抛出下面的异常:

        1. OutOfMemoryError: 请求的堆大小大于可用的堆大小时。

  • 方法区(Method Area):

        线程共享,HotSpot中近似称之为永久代(Permanent Generation)。方法区保存了类信息,如运行时常量池,方法,属性等,随jvm实例启动而被创建,其内存大小可以固定,也可动态扩展,虽然方法区堆的逻辑部分。GC也会对该区进行少量回收,例如类卸载后,但一些简单jvm实现可以不考虑方法区的垃圾回收和压缩,该区会抛出以下异常:

        1. OutOfMemoryError: 当方法区内存不足以满足分配请求时。

  • 运行时常量池(Runtime Constant Pool):

        线程共享,保存了所有类或接口的class文件中的常量池表信息,每一个运行时常量池都从方法区分配内存,即为方法区的一部分,受方法区内存的限制,也可能抛出OutOfMemoryError。

  • 本地方法栈(Native Method Stacks):

        线程私有,它不同于虚拟机栈,它执行的是本地服务方法(如C实现的方法,JNI中),而不是执行java字节,同样会抛StackOverflowError和OutOfMemoryError异常。

  • 另外,还有一个区叫直接内存,它并不属于java虚拟机运行时数据区,所以不受java堆大小限制,比如jdk1.4后提供的NIO中的Buffer,直接使用Native接口访问堆外内存,这样有可能提升性能,但也增加了平台依赖性

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
4 收藏
0
分享
返回顶部
顶部