运行时数据区
线程共享的数据区:堆、方法区
线程隔离的数据区:虚拟机栈、本地方法栈、程序计数器
1.堆
堆是虚拟机管理的内存中最大的一块,在虚拟机启动时创建。用于存放对象实例。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出 OutOfMemoryError 异常。
2.方法区
用于存储虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。其中有常量池。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载。
3.程序计数器
它的作用可以看做是当前线程所执行的字节码的行号指示器。分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。该区域线程私有,所以CPU在线程之间切换时,能够记住执行到哪一步了。
4.java虚拟机栈
线程私有的,它的生命周期与线程相同。每个方法执行的时候创建一个栈帧,其中包含了局部变量表、操作 栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverflowError 异常
如果虚拟机栈扩展时无法申请到足够的内存时会抛出 OutOfMemoryError 异常。
5.本地方法栈
本地方法栈则是为虚拟机使用到的 Native方法服务。native方法称为本地方法。在java源程序中以关键字“native”声明,不提供函数体。其实现使用C/C++语言在另外的文件中编写,编写的规则遵循Java本地接口的规范(简称JNI)。简而言就是Java中声明的可调用的使用C/C++实现的方法。
两种访问方式如下:
Java 堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。
Java 堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,reference 中直接存储的就是对象地址。