依据《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对象,在多线程高并发利用中,是引起线程平安问题的次要数据存储区域、因而,也是程序员最应该关注的中央。