一.类加载过程
1. 加载过程介绍
Java文件经过编译变成 .class 字节码文件,字节码通过 类加载器 被搬运到JVM虚拟机中。
2. 类的生命周期
加载:查找并加载类的二进制数据,在Java堆中创建一个java.lang.class对象
连接:验证、准备、解析
初始化:为类的 静态变量 赋予正确的初始值
使用:new出对象程序中使用
卸载:执行垃圾回收
验证:文件格式验证、元数据验证、字节码验证、符号引用验证
准备:为类的静态变量分配内存,并将其初始化为默认值
解析:把类中的符号引用转换为直接引用
3. 类加载器
启动类加载器(BootStrap ClassLoader):一般由C++实现,是虚拟机的一部分,职责是将JAVA_HOME路径下的\lib目录中能被虚拟机识别的类库rt.jar加载到虚拟机内存中。
扩展类加载器(Extention ClassLoader):由Java实现,独立于虚拟机的外部。该类加载器主要职责将JAVA_HOME路径下的\lib\ext目录中的所有类库,开发者可以直接使用扩展器。
系统加载器(App ClassLoader):指定classpath下面的jar包直接面向我们用户的加载,它会加载classpath环境变量里定义的路径的jar包和目录。我们自己编写的代码以及使用的第三方jar包通常由它来加载。
这里要涉及到一个模型叫做【双亲委派模型】
-
自底向上检查类是否被加载,自顶向下尝试加载类。
-
即在类加载的时候,系统会首先判断当前类是否被加载过,已经被加载的类会直接返回,否则才会尝试加载。
-
加载的时候,首先会把该请求委派给父类加载器的loadClass() 处理,因此所有的请求最终都应该传送到顶层的启动类加载器BootstrapClassLoader。
-
当父类加载器无法处理时,才由自己来处理。当父亲加载器为null时,会使用启动类加载器BootstrapClassLoader作为父亲加载器。
-
双亲委派模型保证了Java程序的稳定运行,可以避免类的重复加载,也保证了Java的核心API不被篡改。
二.垃圾回收
1. 如何确定对象已死
引用计数算法
在对象添加一个引用计数器,每当对象在一个地方被引用,则计数器加一;每当对象引用失效,计数器减一。计数器为0,则表示对象没有被引用。
可达性分析算法
沿着GC Roots的根节点开始进行搜索,凡是在引用链上就不会被回收。
2. 垃圾回收算法
标记-清除:对无效的对象进行标记,然后清除。
标记-复制:把Java堆分成两块,把存活的对象全部移动另一块区域,把使用的空间一次清理掉,这样就使每次的内存回收都是对内存区间的一半进行回收。
标记-整理:进行标记之后,存活的对象会移动到堆的一端,直接清理存活对象以外的区域就可以了。即避免了内存碎片也不存在堆空间浪费的说法。每次进行拦击回收的时候,都要暂停所有的用户线程。
3. 垃圾收集器
- serial收集器:串行收集器进行垃圾收集工作的时候必须暂停其他所有的工作线程;新生代采用标记-复制算法。老年代采用标记-整理算法。
- serial old收集器
- parnew收集器:是串行收集器的多线程版本;新生代采用标记-复制算法。老年代采用标记-整理算法。
- parallel scavenge收集器:重点关注吞吐量 JDK1.8默认使用的是parrale scavenge + paralle old,新生代采用标记-复制算法,老年代采用标记-整理算法。
- parralle old 收集器:是parallel scavenge的老年代版本,使用多线程标记-整理算法
- cms 收集器:他实现了让垃圾收集线程与用户线程同时工作。标记-清除算法,无法处理浮动垃圾,导致收集结束会有大量碎片产生。
- G1 收集器:主要针对配备多颗处理器以及大容量内存的机器,以极高概率满足GC停顿时间要求的同时具备高吞吐量性能特征。整体是基于标记-整理算法,局部是基于标记-复制算法。
三.运行时数据区域
线程私有:程序计数器、虚拟机栈、本地方法栈
线程共享:堆、方法区
3.1 Java堆
存储new出来的对象,不存放基本类型和对象引用,垃圾回收器主要工作在这块区域。
3.2 方法区
存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
3.3 虚拟机栈
每一个方法调用都会有对应的栈帧被压入栈中,调用完后都会有一个栈帧被弹出。
栈帧拥有:局部变量表、操作数栈、动态链接、方法返回地址。
存放基本数据类型(boolean、byte、char、short、int、float、long、double)以及对象的引用。
3.4 本地方法栈
虚拟机使用到的native方法服务。
3.5 程序计数器
字节码解释器通过 程序计数器 来一次读取指令,从而实现代码的流程控制。
在多线程情况下,程序计数器用于记录当前线程执行的位置。
四.Java堆
新生代:Eden区、Survivor:S0 + S1
老年代:Old Generation
元空间:Metaspace
4.1 Minor GC 工作原理
初次创建的对象存放在新生代的Eden区
第一次触发MinorGC对象被转移到Survivor区的某一块区域
再次触发Minor GC的时候,Eden区的对象连同一块Survivor区的对象一起,被转移到了另一块Survivor区
4.2 Full GC 工作原理
老年代是存储长期存活的对象的,占满时就会触发我们最常说的Full GC,期间会停止所有线程等待GC的完成。
来自
因为博客的知识是直击JVM的靶心,基本是干活。这篇大部分的读书笔记都是来自【公众号:楼仔】