JVM 内存模型以及分区
class File: java 文件编译后的文件
Class Loader:类加载器,把class 文件加载到JVM中
加载器分为:
- 根加载器
- 扩展加载器
- 应用程序加载器
- 自定义加载器
加载顺序:
逐层向上询问是否已经加载
自顶向下尝试是否可加载
也就是双亲委派模型
Execution Engine: 执行引擎,其负责解释命令,然后提交给操作系统执行
Native Interface:本地接口的作用是融合不同的编程语言为java所用,现在已经比较少见了。
Native Method Stack:本地方法栈:它的具体做法是Native Method Stack中登记native方法,在Execution Engine 执行时加载本地方法库。
Program Counter Register: PC寄存器,他就相当于一条我们自定义的执行顺序,可以让程序按照我们的顺序严格执行。
JAVA运行栈: 主管java程序的运行,正所谓 栈管运行、堆管存储 就是这个栈。它的生命周期是跟着线程的,线程结束内存释放,对于栈来说不存在垃圾回收问题,8种基本数据类型、对象的引用变量、实例方法都是在栈中分配
Method Area: 方法区,供各线程共享的运行时内存区域,存储了每一个类的结构信息,也就是经过Class Loader解析之后形成的Class模板。
Heap: 堆,需要存放我们new出来的对象,具体堆内存划分如下:
此图与JDK8为例,元空间取代了JDK7以及之前的永久代,但现在在逻辑上元空间还在堆内存中,但实际上元空间已经脱离了堆直接在本地内存中。
堆内存中的GC
首先堆内存中分为新生代和养老区比例为1:2,所有线程进来之后只有经过GC垃圾回收15次的Minor GC扫描屠杀并且没被回收才会进入养老区。当养老区的线程也满了之后,会产生Full GC对养老区进行回收,若养老区的线程无法回收,则会报OOM(OutOfMemoryError)
在新生区又分为Eden、From、To 三个区域比例为(8:1:1),当有线程经过一次GC扫描而没有被回收时 ,就会进入From 区再经过一次还没被回收则进入To区,循环往复,经过15次还未被GC 回收则进入养老区。
三大GC算法 :
- 复制算法:效率高,浪费了TO空间,没有内存碎片
- 标记清除:效率低,节省空间,有内存碎片
- 标记压缩:效率更低,节省空间,没有内存碎片
当我们new一个对象时,对象各个部分在JVM中的存储如下图: