Java内存区域-堆,程序计数器

倖福魔咒の 提交于 2020-01-16 19:58:36

Jvm运行时数据区域-堆,程序计数器

Java堆

堆:Java堆是内存中最大的的一块。Java堆是所有线程共享的的一块内存区域,此内存唯一的目的存放对象实例。几乎所有对象的实例都在这里分配内存。这一点在Java虚拟机规范中描述:所有的对象实例以及数据都要在堆上分配,但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配,标量替换优化技术将会导致一下微妙的变化发生,所有的对象都分配在堆上也渐渐的变得不是那么绝对了。

Java堆是垃圾收集器管理的主要区域(GC堆),现在采用分代收集算法,Java堆分为新生代,和老年代;再细致一点有Eden空间,From Survivor空间,To Survivor空间等。从内存分配的角度来看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)。无论如何划分,都与存放的内容无关,无论哪个区域,存放任然都是对象实例,进一步划分的目的是为了更好的回收内存,或者更快的分配内存。

根据Java虚拟机规定,Java堆可以物理不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现是,既可以实现固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展实现的(t通过-Xmx和-Xms控制(有遇到过))。如果在堆中没有内存完成实例分配,并且无法在扩展时,将会抛出OutOfMemoryError异常。

程序计数器

程序计数器:是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号执行器。字节码解释器工作就是通过改变这个计数器的值来选取下一条执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个计数器来完成。

由于Java虚拟机的多线程是通过线程切换轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。因此,为了线程切换后恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间程序计数器互不影响,独立存储,所以是线程私有的。

如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令位置;如果正在执行的是Native方法,这个计数器值则为空(Undefined)。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!