0
点赞
收藏
分享

微信扫一扫

了解 JVM - 认识垃圾回收机制与类加载过程

Aliven888 2023-07-24 阅读 61

前言

本篇通过介绍JVM是什么,认识JVM的内存区域的划分,了解类加载过程,JVM中垃圾回收机制,从中了解到垃圾回收机制中如何找到存活对象的方式,引用计数与可达性分析的方式,再释放垃圾对象时使用的方式,标准清除,复制算法,标准整理,分代回收等等,如有错误,请在评论区指正,让我们一起交流,共同进步!


文章目录


本文开始

1. 什么是JVM?

JVM: Java虚拟机,通过软件模拟具有硬件功能,运行在一个完全隔离的环境中的完整计算机系统;

2. 认识JVM内存区域的划分

JVM内存区域图示:

问题:查看变量的形态,也就是根据代码判断属于堆,栈还是方法区?
① 堆: 成员变量;(new 出来的对象存放其中)
② 栈:局部变量;(维护方法直接的调用关系)
③ 方法区:静态变量;(放类加载后的类对象, 被static修饰的)
【注】变量处在什么区域与变量类型无关;

线程私有的内存:每个线程都有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储;

  • 栈包括本地方法栈和虚拟机栈;
    本地方法栈:给JVM内部本地方法使用;
    虚拟机栈:给java代码使用;
  • 程序计数器:记录当前程序执行到那个指令了;
  • 堆:存储程序中创建的对象
  • 方法区:存放类加载后的类对象;- 静态变量;

【注】线程共享:堆与元数据区; 线程私有:栈(包括虚拟机栈,本地方法栈)与程序计数器;

例如:

	void function() {
		Student s = new Student();
	}
	//s是引用类型,是局部变量,处在栈上,而new Student()是对象,处在堆上;

3. 认识类加载过程

类加载:把 .class 文件加载到内存 得到类对象的过程;

类加载过程:
加载:找到.class文件,读取文件内容;
验证:验证.class文件是否符号规范要求;.class文件有明确的数据格式;
准备:给类对象分配内存空间(给类变量(static修饰的静态变量)分配的内存空间是未初始化,默认全是0,此时静态变量也是0);
例如:public static int value = 66; //此时准备是给value分配空间,初始化为0,不是66;
解析:针对字符串常量进行初始化;
初始化常量的过程: Java 虚拟机将常量池内的 符号引用 替换为 直接引用 的过程;
符号引用:处于相对位置,字符串常量在.class文件中存在,这时只知道他们之间的相对位置也就是符号引用;
直接引用:处于实际位置,加载到内存中知道位置就是实际内存位置也就是直接引用;
初始化:针对类对象进行初始化;(初始化静态成员,执行静态代码,类有父类也需要加载父类)

4. 类加载中的双亲委派模型

4.1 触发类加载时机 - 类加载是非必要,不加载
1)创建了类的实例
2)使用类的静态方法/静态属性
3)使用子类,触发父类的加载

4.2 双亲委派模型
双亲委派模型作用:在类加载阶段,找.class文件;

JVM加载类会使用类加载器这里简单介绍一下;
JVM中内置的三个类加载器:
① BootStrap ClassLoader: 负责加载Java标准库中的类
② Extension ClassLoader: 负责加载一些非标准的 Sun/Oracke扩展的库中的类;
③ Application ClassLoader: 负责加载项目中自己写的类,和第三方库中的类;

类加载过程图:

5. JVM中的垃圾回收机制

5.1 GC是什么?

GC是垃圾收集的意思;帮助程序员自动释放内存的;

JVM主要释放哪个区域? =》释放 堆区域

5.2 垃圾回收的两个阶段

5.2.1 第一阶段:找GC对象,看对象是否存活; - 找垃圾

如何找垃圾:Java中使用对象,只能通过引用,所以通过判断一个对象是否有引用指向就可以了;所以引入下面两种方法;

  • 引用计数法:给对象里安排一个额外空间,保存一个整数,表示该对象有几个引用指向;Java中不使用, Python,PHP使用
  • 可达性分析法:(Java中使用)把对象之间的引用关系,理解为一个树形结构,从一些特殊起点出发,进行遍历,只要能遍历到的对象,就是可达的,把不能访问到的对象,也就是不可达的当作垃圾;

通过一个树形结构图来看一下:

5.2.2 第二阶段:释放垃圾对象

三种策略:
1)标记清除:先标记出回收对象,再直接释放垃圾对象内存;
产生问题:会产生大量内存碎片;清理完垃圾对象产生大量内存碎片,剩余的内存空间即使很多,但都是碎片化的,如果要申请一段连续的空间可能都申请不到;
图示:

2)复制算法: 解决了内存碎片问题;
复制算法过程:把整个内存空间分成两段(为了好描述过程,这里把内存空间分为a,b,a与b一样),一次只使用一半;如果使用a内存,将a内存中不是垃圾对象的拷贝到没有使用的另一边b内存中,然后再统一释放内存;
图示复制算法:

3)标记整理
标记整理思想:结合上述标记清除,标记整理在其上在加上一个从后向前搬运元素的过程;
标记整理图示:

5.3 JVM的分代回收机制

分代回收机制:综合上述思想,针对不同的情况,使用不同的策略对垃圾进行回收;
分代回收图示:

分代回收过程:
1)·新创建的对象存放到伊甸区;
2)伊甸区的对象,经过第一轮GC,会通过复制算法,拷贝到生存区;生存区分为两半,大小相等,每次只使用一半;
在生存区中是垃圾对象就淘汰,不是垃圾对象就复制到另一半,一直重复上述过程;
3)对象在生存区,经过若干轮GC,年龄增长到 一定程度,就会通过复制算法拷贝到老年代区;
4)进入老年代的对象,年龄比较大,针对老年代的GC扫描频次会降低,消亡率就降低了;
老年代某个对象是垃圾对象了,进行标记整理法清除;
5)特殊情况:对象非常大,直接进入老年代区;原因是大对象进行复制算法成本高,其次大对象也不多;


总结

✨✨✨各位读友,本篇分享到内容如果对你有帮助给个👍赞鼓励一下吧!!
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!

举报

相关推荐

0 条评论