- 运行时数据区包括:堆、虚拟机栈、本地方法栈、方法区、程序计数器
- 方法区和堆是线程共享的,虚拟机栈、本地方法栈、程序计数器是线程私有的
- 程序计数器是线程私有的:每个线程都有自己的程序计数器、虚拟机栈、本地方法栈
- Hostsport JVM中,每个线程都与操作系统的本地系统直接映射:
(1)当一个java线程准备好执行以后,此时操作系统的本地线程也同时创建,一旦调用本地线程初始化成功,操作系统就会调用java线程的run方法。
(2)Java线程执行终止后,本地线程也会回收
程序计数器
程序计数器的作用:存储当前线程下一条执行指令的地址。 由执行引擎来读取下一条指令。
为什么需要程序计数器存储指令地址?
原因: 因为CPU需要不停的切换执行的各个线程,当再次切换回来后,就需要知道从哪儿开始继续执行,也就是说,每个线程工作时都有属于自己的独立计数器。
程序计数器的特点:
(1)程序计数器是线程私有的,每个线程工作时都有属于自己的独立计数器。
(2)执行java方法时,程序计数器是有值的,且记录的是执行线程的下一条字节码指令的地址。
执行native本地方法时,程序计数器的值为空(Undefined)
原因: native方法是java通过JNI直接调用本地C/C++库,而不是java实现的,自然无法产生相应的字节码,native方法的内存模型由对应的实现语言分配的
(3)此内存区域是唯一一个在Java虚拟机规范中没有规定任何内存溢出的区域
堆
见:JVM基础:堆
虚拟机栈
本地方法栈
本地方法是用C或C++编写的方法,本地方法栈就是Java虚拟机通过JNI接口调用本地方法运行时分配的空间。
比较常见的本地方法:Object类中的hashcode、clone、wait、notify、notifyAll方法
方法区
直接内存(注意:不是方法区哈)
(1)直接内存不是虚拟机运行时数据区的一部分,也不是JVM规范定义的内存区域。
(2)直接内存是在java堆外的、直接向系统申请的内存区域
(3)访问直接内存的速度比堆快
常见问题
- 垃圾回收是否涉及栈内存?
垃圾回收不涉及栈内存,因为栈内存中的栈帧内存,是一次次方法调用占用的,每次方法调用结束后会释放占用的栈帧内存,不需要进行垃圾回收。 - 每个线程的栈内存越大越好吗?
不是,因为栈内存越大,只能进行更多次的方法递归调用,但虚拟机能同时运行的线程数量就越少,处理数据的效率就越低。 - 方法内的局部变量是线程安全的吗?
(1)方法局部变量是对象,作为返回值返回,则不是线程安全的,会被其他线程修改
(2)当变量为对象,通过地址引用出入方法内,也不是线程安全的