共计 1459 个字符,预计需要花费 4 分钟才能阅读完成。
依据《JAVA 虚拟机标准》的规定,JAVA 虚拟机在执行 JAVA 程序的过程中会把内存划分为不同的数据区域。不同类型的数据会存储在不同的区域,了解 JAVA 内存区域的工作细节对裂解 JAVA 多线程、线程安全性有着重要意义。
留神,JAVA 内存区域的划分与咱们常说的 java 内存模型 JMM(Java Memery Model) 是两个互不穿插的维度的概念,两者没有任何关系。JMM 次要是将主内存和工作内存的关系、数据从主内存区读取的工作内存、以及从工作内存写回到主内存区、以及不同线程的工作内存间数据同步的问题。
本文次要探讨内存区域的划分,不波及 JMM 相干内容。
从线程隔离角度,能够把这些内存区域分成两局部:线程公有的区域、以及线程共享的区域。 顾名思义,线程公有区域的数据是各线程独享的,因而,存储在线程公有区域的数据不会有线程平安问题。线程共享区域的数据是要在不同线程间共享的,这部分数据才有可能引起线程平安问题。
程序计数器
程序计数器(Programe Counter Register)是属于线程公有区域的数据区。
程序计数器数据区根本是程序员最不须要关怀的区域。
程序计数器是为了管制程序运行、用来记录须要执行的字节码的地址的,为了精确记录多线程环境下每一条线程的执行指令地址,程序计数器数据区必须是线程公有的区域。
办法区
办法区(Method Area)是线程共享的数据区域。
办法区用来存储虚拟机加载的类信息,包含类的元数据、常量、动态变量等。
大家能够反过头来想想,为什么动态变量能够在类的不同实体对象之间共享?也正因为如此,动态变量使用不当的话也很容易引起线程平安问题。
另外,String s=new String(“12345”),那么 s 是否会存储在办法区?s.intern() 呢?
本地办法栈
本地房倒退(Native Method Stack)属于线程公有的数据区。
本地办法栈是为 JAVA 应用到的本地(Native)办法服务的,因为《JAVA 虚拟机标准》没有对本地办法栈做硬性规定,所以,有些虚拟机比方 HotSpot 把本地办法栈和虚拟机栈合二为一了。
虚拟机栈
虚拟机栈(VM Stack)是线程公有的数据区。
虚拟机栈和堆是程序员打交道最多的数据区,也是程序员最须要关怀的内容。
JAVA 虚拟机栈用于存储局部变量,比方 java 办法内定义的变量、办法返回等。每一个 JAVA 办法执行的时候,JAVA 虚拟机都会同步创立一个栈帧(Stack Frame),JAVA 办法的执行过程对应着局部变量的进栈出栈过程。
JAVA 栈保留的是 JAVA 根本类型或对象援用(refrence),保留在虚拟机栈的局部变量表中,以变量槽(slot)来示意。
堆
堆(JAVA Heap)是线程共享的数据区。
JAVA 堆是寄存 JAVA 对象的内存区域,简直所有的 JAVA 对象都存储在 JAVA 堆中。
JAVA 堆也是 JAVA 垃圾回收器(GC)的次要工作对象,不同的垃圾回收器或者垃圾回收算法,会依照不同的形式划分 JAVA 堆,比方新生代、老年代、永恒代 … 等等,不管怎么划分,这样的划分仅仅是为了垃圾回收服务的,并不是 JAVA 堆内存必须依照这样的形式进一步粗疏划分。
存储在线程共享的数据区中的数据,才有可能存在线程安全性问题。 也就是说,办法区、堆内的数据,有可能存在零碎安全性。然而办法区中存储的次要是类的元数据信息以及动态变量,从线程平安角度来看,利用须要重点关注的是动态变量。内存对中存储的是 JAVA 对象,在多线程高并发利用中,是引起线程平安问题的次要数据存储区域、因而,也是程序员最应该关注的中央。