java运行时数据区
1. 程序计数器
程序计数器是一块较小的内存空间。与jvm的虚拟概念中,字节码解释器工作时可以改变程序计数器来选取下一条字节码指令。
程序计数器是线程私有,这很好理解,不多赘述。
当线程正在执行java方法,pc则是记录正在执行的虚拟机字节码指令的地址;如果是本地(native)方式,则pc值为空
2. java虚拟机栈
与pc一样,java虚拟机栈也是线程私有的。当有方法执行的,java虚拟机栈会创建一个栈帧(stack frame)用于存储局部变量表、操作数栈、动态链接、方法出口等。每个方法开始到结束对应栈入栈出栈。
局部变量表存放了编译期克制的各种java虚拟机基本数据类型、对象引用和returnAddress类型。
以上表中数据以Slot(局部变量槽)表示。
对象引用(扩展)
java栈中引用是对象的引用。所以如何使用呢?
主流的访问方式:
- 句柄
- 直接指针
句柄是存放在堆内存中开的一块空间(句柄池)中,句柄的好处是可以将存的数据委托给句柄池。当对象需要移动时(但是栈中的东西引用依旧存在)这是只需修改句柄中的数据便可。
对于所有这种需要跳转一次的数据来说,都需要花一次指针跳转的时间,而直接指针可以直接定位到堆中数据,但是直接指针的缺点是当对象移动后(如果进行gc后的内存重排),对象引用也需要同步更新(笔者对这有些疑惑)
来自该网址
3. 本地方法栈
本地方法栈类似与虚拟机栈,虚拟机栈是虚拟机执行java方法,而本地方法栈是虚拟机使用本地方法。
4. java堆
java堆是虚拟机所管理内存最大的一块。java堆是内存共享的区域。《java虚拟机规范》中描述java堆职责:“所有的对象实列以及数组都应该在堆上分配”。
java堆是垃圾收集器的管理的区域
关于一些其他博客资料中写的"GC堆} ,因为现代大多数垃圾收集器是基于分代理论设计的。比如很多资料中写java堆中可以分为新生代,老年代,新生代分为"from survivor",“to survivor”,“eden”。在《深入理解java虚拟机中》的作者认为这些区域划分仅仅是一部分垃圾收集器的共同特性或者说是设计风格。
java堆中有个TLAB的区域,这个区域可以调整jvm参数手动开启。
new对象后会做哪些事
5. 方法区
方法区与java堆一阿姨那个,是线程共享的区域,该区域用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。