JVM内存结构
JVM的内存结构,是指JAVA在JVM中运行时,在内存里所涉及到的几块区域。
JVM内存结构,分为堆,方法区,虚拟机栈,本地方法栈,程序计数器5块区域。
堆:保存对象实例,所有对象(包括数组)实例都在堆中分配。
方法区:存储被虚拟机加载后的类,静态变量,常量,即时编译器编译后的代码等数据。
虚拟机栈:也叫线程栈,每个线程运行时有自己独立的线程栈,里面存放了线程运行中创建的局部变量,操作栈,动态链接,方法出入口信息呢。
(描述解释:一个本地变量可能是原始类型,在这种情况下,它总是“呆在”线程栈上。
一个本地变量也可能是指向一个对象的一个引用。在这种情况下,引用(这个本地变量)存放在线程栈上,但是对象本身存放在堆上。
一个对象可能包含方法,这些方法可能包含本地变量。这些本地变量任然存放在线程栈上,即使这些方法所属的对象存放在堆上。
一个对象的成员变量可能随着这个对象自身存放在堆上。不管这个成员变量是原始类型还是引用类型。
静态成员变量跟随着类定义一起也存放在堆上。
存放在堆上的对象可以被所有持有对这个对象引用的线程访问。当一个线程可以访问一个对象时,它也可以访问这个对象的成员变量。如果两个线程同时调用同一个对象上的同一个方法,它们将会都访问这个对象的成员变量,但是每一个线程都拥有这个本地变量的私有拷贝。)
程序计数器:可以看成是线程执行时的字节码行号指示器。用于控制程序顺序执行。
分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
如果线程正在执行的是一个Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie
方法,这个计数器值则为空(Undefined)。
此内存区域是唯一一个在Java 虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
本地方法栈:是存放虚拟机使用到的Native方法/常量等信息。
JAVA内存模型
含义:Java内存模型,简称JMM (JAVA Memory Model),是一种复合内存模型的规范,用于屏蔽各种硬件和操作系统的访问差异,保证Java程序在各种平台下对内存访问都能保证效果一致的机制及规范。
Java在并发操作时,可能会遇到原子性问题,可见性问题,有序性问题。JMM可以解决这3种并发编程中遇到的问题。
- 原子性:是指JAVA运行时,保证一段代码CPU开始执行了就执行结束,要么不执行的问题。
可以通过synchronized关键词来保证。 - 可见性:指在并发编程中,多个线程访问一个变量,一个线程改变了这个值,其他线程立即可以看到这个值的改变。
可以通过volatile关键词来实现,来保证线程每次使用时,都重新读取该变量的值。 - 有序性:指保证程序的顺序执行。
可用synchrnized关键词来保证程序的顺序执行。