0%

Java内存模型

写在Java内存模型前面

JAVA依旧是当前比较受欢迎的面向对象的开发语言,Java 编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和静态的语言。
作为程序员摊开来说Java,说起Java一般接下来会有几个定义:JDK、JRE、JVM。
JDK(Java Development kit)是针对开发的产品,是整个Java的核心,它包括了Java运行环境JRE、Java工具和Java基础类库。
JRE(Java Runtime Environment)是运行Java程序所必需的环境的集合,它包括JVM标准实现和Java核心类库。
JVM(Java virtual Machine)Java虚拟机,是整个Java实现跨平台的最核心的产品,能够与性Java写作的软件程序。所有的Java程序会被编译成.class的类文件,这种类文件可以在虚拟机上执行,也就是说,class并不直接操作机器的操作系统,而是经过虚拟机间接的与操作系统交互,有虚拟机将程序解释给本地系统执行。

关于JMM

JMM(Java Memory Model),Java内存模型,其实是一套内存模型规范,屏蔽了各种硬件和操作系统访问差异,保证Java程序在各种平台下对内存的访问的效果都一致。
Java程序的内存的分配是在JVM虚拟机内存分配机制下完成的。
Java内存共分为五部分: 虚拟机栈、 堆、 方法区、 本地方法栈、程序计数器。

程序计数器

这一部分是当前线程锁定执行字节码的行号指示器,是一块较小的内存空间。程序计数器是线程私有的。Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的。
所以在任一确定时刻,一个处理器只会执行一条线程的指令,因此,为了线程切换后能恢复到正确的执行位置,每条线程都是需要一个独立的程序计数器,各条线程之间互相不影响,独立存储。
如果说线程正在执行的是Java方法,计数器记录的就是正在执行的虚拟机字节码指令的地址,如果执行的是Native方法,这个计数器值就是空(Undefined)。这块区域也是为一个在Java虚拟机规范中没有规定任何内存溢出情况的区域。

虚拟机栈

这一部分也是线程私有的,每个方法在执行的时候会创建一个栈桢。每个栈桢存储局部变表、操作数、动态链接、方法返回地址等。每一个方法的调用到执行完毕,对应一个栈桢在虚拟机栈中的如栈和出栈。局部变量表存放了编译器克可知的各种基本数据类型、 对象引用和returnAddress类型(一条指向字节码指令的地址),局部变量表所需的内存空间在编译期间就分配完成,当进入一个方法时,该方法需要的在桢中分配多大的局部变量空间时完全确定的,在运行期间不会改变局部变量表的大小。

本地方法栈

与虚拟机栈的作用和原理相似,区别是虚拟机栈是为执行Java方法服务,本地方法栈是为执行本地方法服务的。

Java中的堆是用来存储对象本身的以及数组(数组引用是存放在Java栈中的),堆是被所有线程共享的,在JVM中只有一个堆。Java堆是垃圾收集器管理的主要区域,因为也被称为GC堆。

方法区

方法区中存储了已经被虚拟机加载的类的信息(包括类的名称、方法信息、属性字段信息)、静态变量、常量以及编译器编译后的代码等。与堆一样,方法区也是被线程共享的区域。Java虚拟机规范堆这个区域的限制非常宽松。除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾回收。运行时常量池时方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息时常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。