在JVM内部,Java内存模型把内存分成了两部分:线程栈区和堆区,一般来讲,可以更加细致的分为五个部分:
Method Area,Heap,VM Stack,Native Method Stack,Progrom Counter Register。
这其中Method Area和Heap属于允许多个线程共享的部分,而VM Stack,Native Method Stack,Progrom Counter Register则不允许线程共享。
先看不允许线程共享的部分。
在Java内存模型中,线程栈区储存的是当前执行的方法所调用的信息,包括该方法本地变量的内容。每个线程都有独立的线程栈,同时每个线程也只能读取自己的线程栈。每个线程私有的栈,生命周期和该线程是一致的。
JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。
当线程相互之间进行通讯时,实质上是在主内存上交换变量的副本。例如,当线程1向线程2发送一个消息时,线程1先在本地内存上生成一个要发送的变量的副本,然后主内存会从线程1的本地内存中接受这个副本,并把这个副本传给线程2的本地内存,线程2从自己的本地内存中接收这个副本,就完成了一次线程中的通信。当然,这只是一个基础的例子,关于线程之间的通信和变量的共享,以后会有更详细的说明。
线程的栈区中,可以储存原始数据类型,例如int,double,boolean型等,也可以存储对象的引用,但是对象实例的具体属性等信息则保存在Heap中。
我在这里简单的把VM Stack和Native Method Stack都理解为线程栈区。而剩下的程序计数器是一块较小的内存区域,作用可以看做是当前线程执行的字节码的位置指示器。分支、循环、跳转、异常处理和线程恢复等基础功能都需要依赖这个计算器来完成。