前言
我理解JVM应该属于Java高阶的知识,之前是通过博客学习这块知识,后来对照着《深入理解Java虚拟机》书籍把重点知识又过了一遍。经过大半个月的学习,我给出我学习的感受。
我感觉其实通过博客学习这块知识其实就够了,因为博客中的知识直击JVM的靶心,基本都是干货,但是对于一些实际的场景用例,博客给的示例不多,这个是通过博客学习唯一的缺点。
通过书籍学习JVM知识,真的感觉这本书太厚了,不建议新人学习,因为这本书也就前5章的内容比较干货,后面的大部分知识可以直接跳过,或者作为选学的知识,比如你学习书籍中的“虚拟机字节码执行引擎”、“前端编译与优化”等章节,我感觉这些知识完全没有学习的必要,都是些“八八股文”,完全可以等需要的时候再学。但是通过书籍可以作为博客学习的补充,因为里面很多的实战示例还是非常不错的,然后有些重点知识,书中也讲解的非常详细,比如“垃圾收集器”。
那下面我们就把这个系列学习的知识总结一下吧~~
类的加载过程
加载过程介绍
如果 JVM 想要执行这个 .class 文件,我们需要将其装进一个类加载器 中,它就像一个搬运工一样,会把所有的 .class 文件全部搬进JVM里面来。
重点知识:
- Java文件经过编译后变成 .class 字节码文件
- 字节码文件通过类加载器被搬运到 JVM 虚拟机中
- 虚拟机主要的5大块:方法区,堆都为线程共享区域,有线程安全问题,栈和本地方法栈和计数器都是独享区域,不存在线程安全问题,而 JVM 的调优主要就是围绕堆,栈两大块进行。
类加载流程
类加载的过程包括了加载、验证、准备、解析、初始化五个阶段。在这五个阶段中,加载、验证、准备和初始化这四个阶段发生的顺序是确定的,而解析阶段则不一定,它在某些情况下可以在初始化阶段之后开始,这是为了支持Java语言的运行时绑定(也成为动态绑定或晚期绑定)。另外注意这里的几个阶段是按顺序开始,而不是按顺序进行或完成,因为这些阶段通常都是互相交叉地混合进行的,通常在一个阶段执行的过程中调用或激活另一个阶段。
- 加载,查找并加载类的二进制数据,在Java堆中也创建一个java.lang.Class类的对象
- 连接,连接又包含三块内容:验证、准备、初始化。1)验证,文件格式、元数据、字节码、符号引用验证;2)准备,为类的静态变量分配内存,并将其初始化为默认值;3)解析,把类中的符号引用转换为直接引用
- 初始化,为类的静态变量赋予正确的初始值
- 使用,new出对象程序中使用
- 卸载,执行垃圾回收
类加载器
加载一个Class类的顺序也是有优先级的,类加载器从最底层开始往上的顺序是这样的:
- BootStrap ClassLoader:rt.jar
- Extention ClassLoader: 加载扩展的jar包
- App ClassLoader:指定的classpath下面的jar包
- Custom ClassLoader:自定义的类加载器
垃圾回收
如何确定对象已死
通常,判断一个对象是否被销毁有两种方法:
- 引用计数算法: 为对象添加一个引用计数器,每当对象在一个地方被引用,则该计数器加1;每当对象引用失效时,计数器减1。但计数器为0的时候,就表白该对象没有被引用。
- 可达性分析算法: 通过一系列被称之为“GC Roots”的根节点开始,沿着引用链进行搜索,凡是在引用链上的对象都不会被回收。
就像上图的那样,绿色部分的对象都在GC Roots的引用链上,就不会被垃圾回收器回收,灰色部分的对象没有在引用链上,自然就被判定为可回收对象。
垃圾回收算法
标记--清除算法
见名知义,标记--清除算法就是对无效的对象进行标记,然后清除。
复制算法
标记--复制算法就是把Java堆分成两块,每次垃圾回收时只使用其中一块,然后把存活的对象全部移动到另一块区域。
标记--整理算法
标记--整理算法算是一种折中的垃圾收集算法,在对象标记的过程,和前面两个执行的是一样步骤。但是,进行标记之后,存活的对象会移动到堆的一端,然后直接清理存活对象以外的区域就可以了。这样,既避免了内存碎片,也不存在堆空间浪费的说法了。但是,每次进行垃圾回收的时候&#x