JVM(虚拟机,Java Virtual Machine)的内存空间分类:
程序计数器
堆内存
JVM虚拟机栈
本地方法栈
方法区
程序计数器:
程序计数器是什么:
一块较小的内存空间,指向字节码解释器正在执行的行数,记录了当前线程正在执行的那一条字节码指令
为每个线程私有的,随着线程创建而生成,随着线程结束而释放
程序计数器的作用:
1.字节码解释器通过不断变换程序计数器的值来执行不同的指令
2.在多线程环境下,记录每个线程执行到的指令(程序计数器为每个线程私有的),以便切换回线程后可以继续往下执行
JVM虚拟机栈:
JVM虚拟机栈是什么:
描述方法执行的内存模型,在执行到某个方法时,会为这个方法生成相应的帧栈,帧栈保存了方法的局部变量表,出口信息,操作数栈等信息
JVM虚拟机栈的特点:
为每个线程私有,随着方法创建而生成,随着方法结束而释放
很多书上常说:JVM内存分为栈(保存局部变量)和堆(保存new的对象和数组),这句话不够严谨,正确的说法是:JVM内存分为栈(JVM虚拟机栈中的帧栈的局部变量表)和堆(保存new的对象和数组)局部变量表在编译的时候就已经确定了大小
JVM虚拟机栈的大小是可以设置的:
设置为允许动态变化:当帧栈过多,导致内存不够时,无法生成方法对应的帧栈,抛出OutOfMemory异常
设置为固定大小:当频繁地嵌套调用函数,帧栈过多,无法生成方法对应的帧栈,抛出StackOverFlow异常
StatckOverFlow和OutOfMemory的区别:
StatckOverFlow:线程申请的栈深度超过了最大深度,内存可能还有很多
OutOfMemory:JVM虚拟机栈的空间满了,无法分配新内存
本地方法栈:
和JVM虚拟机栈一样,唯一的区别是管理对象的不同:
本地方法栈:管理本地方法(native方法)
JVM虚拟机栈:管理Java程序的方法
堆:
堆是什么:
new出来的对象或者数组,注意new出来的对象只在堆内存中保存属于各个实例的成员变量,并不包括成员方法(成员方法会在调用方法的时候存入在JVM虚拟机栈中)。一个类的多个实例都有属于自己的成员变量,每次new对象时都需要在堆中分配内存,但是多个实例共享该类的方法,并不是每次new对象都需要拷贝一份方法到堆内存中,在堆内存中该分配的内存,由垃圾回收器(GC)进行管理回收。
堆的特点:
JVM启动时就分配大小,并且大小可变
所有的线程共用一个堆
方法区:
方法区是什么:
堆中的一块逻辑区域,存放类信息,静态变量,常量池
方法区的特点:
所有线程共享
在堆中为永久代,很少需要回收,回收的主要目的是清理常量池和卸载类
常量池:
我们一般在一个类中通过public static final来声明一个常量。这个类被编译后便生成Class文件,这个类的所有信息都存储在这个class文件中。
存放public static final变量,或者String.intern()等变量