Java的内存区域划分:–6大区域
一.线程私有内存–3个
线程私有指这三块区域的生命周期与线程的生命周期相同,随着线程的创建而创建,随着线程的销毁而回收,不同线程间这三块内存彼此隔离。
-
程序计数器(每个线程都需要一个程序计数器来记录中断的位置,所以是线程私有的)
a. 定义:在执行字节码的过程中,CPU突然中断去执行别的任务,当前中断位置被记入程序计数器,当CPU回来继续工作时,从程序计数器中读取中断位置从而继续工作。b. 作用:当前线程正在执行的字节码行号指示器,是六大区域中唯一一块不会产生OOM(OutOfMemoryError)异常的区域。
c. 若执行的是java方法,则程序计数器记录的是正在执行的虚拟机字节码指令的地址。不能记录本地方法,若执行的是native方法,则计数器值为空(undefined)。
-
虚拟机栈
a.定义:描述Java方法执行的内存模型: 每个方法执行的同时都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用到结束的过程,都对应一个栈帧在虚拟机栈中入栈到出栈的过程,生命周期与线程周期相同。b.局部变量表(就是通常所说的栈内存区):存放了编译器可知的各种基本数据类型(8大基本数据类型),对象引用。局部变量表所需的内存空间在编译期间完成分配,在方法运行期间不会改变他的大小。
c.两种异常:
1) StackOverFlowError:栈溢出错误:线程请求的栈深度大于虚拟机允许的栈深度;
2) OOM:无法扩容时抛出异常:在虚拟机栈可以扩容的前提下,如果扩展时申请不到足够的内存;
d.-Xss:设置栈的大小 -
本地方法栈
a.定义:描述native方法的内存模型
在HotSpot虚拟机上(默认的虚拟机):本地方法栈与虚拟机栈是一块空间。
也有:
1) StackOverFlowError:栈溢出错误:线程请求的栈深度大于虚拟机允许的栈深度;
2) OOM:无法扩容时抛出异常:在虚拟机栈可以扩容的前提下,如果扩展时申请不到足够的内存;
二.线程共享内存–3个
线程共享指所有线程共享此三块区域内存,彼此不隔离
-
Java堆(GC堆,垃圾回收主要负责的区域)
Java Heap是JVM管理的最大内存区域,虚拟机启动时创建java堆,唯一目的就是存放对象实例; 所有的对象实例及数组要在堆上分配,但是随着技术发展,所有的对象都分配在堆上也变得不绝对了; Test test = new Test();--->test:对象引用,存放在栈里;new Test():对象实例,存放在堆里 java堆可以处于物理上不连续的空间,只要逻辑上是连续的就可以 如果在堆中已经没有可以完成对象实例的分配的内存,并且也不能再扩展堆时,会抛出OutOfMemoryError异常; 虚拟机的内存扩展: -Xmx:设置堆的最大值 -Xms:设置堆的最小值
-
方法区(JDK8之前称为“永久代”)
用于存储已被JVM加载的类信息,常量,静态变量;
-
运行时常量池
是方法区的一部分,存放字面量和符号引用 字面量:直接写出来的值 符号引用:通过符号引用找到指定的类,再通过引用变量找到堆空间 Java.util.Test test = new Test(); 通过Java.util包(符号引用)找到指定的类(Test),再通过引用变量(test)找到堆空间