java 线程栈空间_Java运行时数据区和线程栈

Java运行时数据区和线程栈

Java运行时数据区

a50841141aa2d47d8dc42ecb6b879f01.png

上图是Java运行时数据区的逻辑图,之所以说是逻辑图,那是因为虚拟机规范只是描述虚拟机包含方法区、堆、Java栈、PC寄存器、本地方法栈,实现者只要实现虚拟机的功能即可,因为虚拟机规范没有明确指定这几个数据区的从属和包含关系。

方法区(Method Area)

关于堆的描述,我们直接引用虚拟机规范《The Java® Virtual Machine Specification Java SE 8 Edition》2015-02-13版本,2.5.4节

“The Java Virtual Machine has a method areathat is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the "text" segment in an operating system process. It stores per-class structures such as the run-time constant pool,field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization.”

方法区共享于Java线程。方法区用于存储:类的结构、运行时常量池、字段、方法数据、构造方法和普通方法的字节码内容、特殊方法。

方法区的类结构、字段等信息在,在类型加载时得到,并存储到到方法区的。虽然方法区共享于Java线程,但类加载阶段只能是单线程进行,所以在类加载阶段不存在并发的情况。由于类的静态变更也存储在方法内,所以类的静态变量在使用过程中是需要注意共享的问题的。

方法区也存在也需要进行内存管理(即垃圾回收),由实现虚拟者选择具体的技术。方法区是一个逻辑区,所以方法区可以是独立于堆的内存,也可以是堆中划分出来的一部分,这个最决于虚拟机实现者具体实现和版本。

常量池就是该类型的直接常量和其它类型的字段、方法的符号引用。虚拟机必须为每个被加载的类型维护一个常量池。常量池也属于方法区的中一部分内容。

堆(Heap)

关于堆的描述,我们直接引用虚拟机规范《The Java® Virtual Machine Specification Java SE 8 Edition》2015-02-13版本,2.5.3节

“The Java Virtual Machine has a heapthat is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated.”

首先,Heap共享于所有Java线程,然后用于分配类实例和数组内存。通俗点解释就是:一个Java虚拟机实例只有一个堆,用于存储类实例和数组,并且堆是线程共享的。这就很好解释了多线程共享堆数据要通过使用同步规则控制的原因了。

“Heap storage for objects is reclaimed by an automatic storage management system (known as a garbage collector);”

规范明确虚拟机的实现要一套自动管理系统管理存储的对象,即垃圾回收机制。但Java虚拟机并指明具体使用那些技术去管理对象的回收,虚拟机的实现者可以使用任意技术进行回收。甚至极端情况下,可以不释放所持有的对象,直接抛异常,因为这也是一种对象管理方式。

Java栈(Java Virtual Machine Stacks)

Java线程栈的描述,我们直接引用虚拟机规范《The Java® Virtual Machine Specification Java SE 8 Edition》2015-02-13版本,2.5.2节

“Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.”

Java线程栈从线程创建时存在,并且是私有的。线程栈用户存储栈帧,栈帧用于存储局部变量、中间运算结果。所以局部是不存在并发的问题,因为每个栈是私有的。

Java线程栈属于一个逻辑栈,和方法区一样,由虚拟机的实现决定栈的位置,可能是堆的一部分,也可能是单独栈区。

虚拟机只会对Java栈进行二种操作:以栈帧为单位的压栈和出栈。栈帧由:局部变量区、操作数栈、帧数据区。

PC寄存器(The pc Register)

每一条Java虚拟机线程都有自己的PC寄存器。如果这个方法不是本地方法的,那PC寄存器就保存Java虚拟机正在执行的指令的地址,如果该方法是本地的,那PC寄存器的值是undefined。PC寄存器的容量可以存储一个returnAddress类型的数据或者一个本地指针。

本地方法栈

线程进入使用Java以外的语言编写的方法,进入本地方法栈。本地方法不受虚拟机约束,可以实现做它任何想做的事情。具体由本地方法实现决定。另外本地方法栈还可以再回到Java方法中,再一次进入Java线程栈。

Java的线程与栈帧

假设我们的代码如下图所示,方法test调用方法add,其中方法add把两个参数相加,并返回结果。

48941e6244a50efda900638d519e31d7.png

每当Java线程调用方法时,虚拟机就在Java线程栈中压入一个帧,方法return或方法抛出异常时弹出栈。当线程从test方法调用add方法时,压入add方法栈帧,则当前栈帧add帧。执行add方法后,返回结果并弹出当前帧,然后test方法的栈帧成了当前帧。

f2c6b6bf47458b0886170839177c60ff.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值