java虚拟机运行时数据区分为5个部分
- 方法区
- 堆
- 虚拟机栈
- 本地方法栈
- 程序计数器
线程共享:方法区、堆
线程私有:虚拟机栈、本地方法栈、程序计数器
程序计数器
程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需依赖其完成。可以看成是当前线程所执行的字节码的行号指示器,字节码解释器就是通过改变这个计数器来选取下一条要执行的字节码指令。
在一个时间点,一个处理器只会执行一个线程,每条线程都有一个独立的程序计数器
java方法:记录正被执行的字节码指令地址
本地(native)方法:为空(Undefined)
虚拟机栈
java虚拟机栈是线程私有的,生命周期与线程相同
每个方法被执行时,虚拟机栈就会同步创建一个栈帧
每个方法从调用到执行完,就对应一个栈帧在虚拟机栈中的入栈到出栈
栈帧:存储局部变量表,操作数栈等
局部变量表:存放编译期可知的各种java基本数据类型和对象引用,在局部变量表中存储空间以局部变量槽(slot)表示,64位的long和double占两个槽位,其他的占一个。局部变量表所占用的槽位数量在编译期间就已经确定好,在方法运行时不会改变
本地方法栈
与虚拟机栈作业类似,区别在于
虚拟机栈为执行的java方法服务,
本地方法栈为虚拟机使用到的本地方法服务
堆
java堆是所有线程共享的一块内存区域,几乎所有对象实例以及数组都在堆里分配(现在是,以后有可能改变),是垃圾收集器管理的内存区域
方法区
堆的一个逻辑部分,但又叫做“非堆”,用于跟堆区分开来,线程共享,用于存放已经被虚拟机加载的类型信息、常量、静态变量、即时编译后的代码缓存等
在Hotspot中使用永久代来实现方法区
在jdk 7,把放在永久代中的字符串常量池、静态变量等移出
在jdk 8,彻底废弃永久代,改用在本地内存中实现的元空间来代替
运行时常量池
是方法区的一部分
除了预先置入Class文件中的常量池外,运行期间也可以将新的常量放入池中,如String 类中的intern()方法
直接内存
并不是虚拟机运行时数据的一部分,但使用较为频繁
在jdk 1.4 中加入的NIO(New Input/Output)类,引入基于通道和缓冲区的I/O 方式,可以利用Native 函数库直接分配堆外内存,然后通过存在堆内的DirectByteBuffer对象作为引用进行操作