当前位置: 首页 > 后端技术 > Java

JAVA内存区域划分

时间:2023-04-02 01:18:05 Java

根据《JAVA虚拟机规范》的规定,JAVA虚拟机在JAVA程序执行过程中会将内存划分为不同的数据区域。不同类型的数据将存储在不同的区域。了解JAVA内存区的工作细节对于理解JAVA多线程和线程安全具有重要意义。注意,JAVA内存区的划分和我们常说的Java内存模型JMM(JavaMemoryModel)是两个不相交的维度的概念,两者没有任何关系。JMM主要是关于主内存和工作内存的关系,工作内存从主内存区域读取数据,从工作内存写回到主内存区域,以及内存和主内存之间的数据同步不同线程的工作内存。本文主要讨论内存区域的划分,不涉及JMM相关内容。从线程隔离的角度来看,这些内存区可以分为两部分:线程私有区和线程共享区。顾名思义,线程私有区中的数据是每个线程独享的。因此,存放在线程私有区的数据不会有线程安全问题。线程共享区中的数据必须在不同线程之间共享,这部分数据可能会引起线程安全问题。程序计数器程序计数器(ProgramCounterRegister)是属于线程私有区域的数据区域。程序计数器数据区基本上是程序员不需要关心的区域。程序计数器用来控制程序的运行,记录需要执行的字节码的地址。为了在多线程环境下准确记录每个线程的执行指令地址,程序计数器数据区必须是线程私有区。方法区方法区(MethodArea)是线程共享的数据区。方法区用来存放虚拟机加载的类信息,包括类元数据、常量、静态变量等。大家可以反过来想,为什么一个类的不同实体对象之间可以共享静态变量呢?正因为如此,静态变量使用不当很容易造成线程安全问题。另外,Strings=newString("12345"),s会不会存放在方法区?s呢?实习生()?本地方法栈(NativeMethodStack)属于线程的私有数据区。本地方法栈服务于JAVA使用的本地(Native)方法。由于《JAVA虚拟机规范》没有对native方法栈做硬性规定,一些虚拟机如HotSpot将native方法栈和虚拟机栈合二为一。虚拟机栈虚拟机栈(VMStack)是一个线程私有的数据区。虚拟机栈和堆是程序员接触最多的数据区,也是程序员最需要关心的内容。JAVA虚拟机栈用于存放局部变量,如java方法中定义的变量,方法返回等。每个JAVA方法执行时,JAVA虚拟机都会同步创建一个栈帧(StackFrame),JAVA方法的执行过程对应局部变量的出栈出栈过程。JAVA栈保存的是Java基本类型或对象引用(refrence),存放在虚拟机栈的局部变量表中,用变量槽(slot)表示。堆(JAVAHeap)是线程共享的数据区。JAVA堆是存放JAVA对象的内存区域,几乎所有的JAVA对象都存放在JAVA堆中。JAVA堆也是JAVA垃圾收集器(GC)的主要工作对象。不同的垃圾收集器或者垃圾收集算法会对JAVA堆进行不同的划分,比如新生代,老年代,永久代等等,不管怎么划分,这种划分只是为垃圾回收服务,并不是说JAVA堆内存一定要这样划分。只有存储在线程共享的数据区的数据才可能存在线程安全问题。也就是说,方法区和堆中的数据可能具有系统安全性。而类和静态变量的元数据信息主要存放在方法区。从线程安全的角度来看,应用程序需要关注静态变量。JAVA对象存储在内存堆中,是多线程高并发应用中导致线程安全问题的主要数据存储区。因此,也是程序员最应该注意的地方。