JVM相关知识点
JVM的基本结构
JVM由三个主要的子系统构成
- 类加载子系统
- 运行时数据区(内存结构)
- 执行引擎
类加载子系统
类的生命周期
1、加载
将.class文件从磁盘加载到内存的过程。
2、连接
2.1、验证
验证字节码文件的正确性。
2.2、准备
给类的静态变量分配空间并赋予默认值(基本类型为基本类型的默认值,对象为null)
2.3、解析
加载类所引用的其他的类。将符号引用转变为直接引用(静态连接)。
3、初始化
为类的静态变量赋予实际的值,执行静态代码块。
4、使用
5、卸载
类加载器
BootstrapClassLoader(启动类加载器)
最顶层的加载类,由C++实现,负责加载 %JAVA_HOME%/lib目录下的jar包和类或者或被 -Xbootclasspath参数指定的路径中的所有类。
ExtensionClassLoader(扩展类加载器)
主要负责加载目录 %JRE_HOME%/lib/ext 目录下的jar包和类,或被 java.ext.dirs 系统变量所指定的路径下的jar包。
AppClassLoader(应用程序类加载器)
面向我们用户的加载器,负责加载当前应用classpath下的所有jar包和类。
UserClassLoader(用户自定义类加载器)
类加载机制
全盘负责委托机制
当一个ClassLoader装载一个类时,除非显示地使用另一个ClassLoader,则该类所依赖及引用的类也由这个CladdLoader载入。
双亲委派机制
先让父加载器加载,如果父加载器不能加载则再由自己进行加载。
优势:防止核心库被篡改;避免类的重复加载。
运行时数据区(内存结构)
绿色为共享区域,黄色为线程的私有区域
JVM调优主要是调堆与方法区,私有区域由JVM自动管理
1、方法区
存放静态变量、常量、类信息(构造方法/接口定义)、运行时常量池
2、堆
存放对象实例,堆有可以划分为新生代和老年代
2.1、新生代
由Eden区和两个Survivor区(From、To)组成、约占堆大小的1/3,三者大小比例为8:1:1(默认可配置)。当Eden区空间不足时触发Minor GC,通过GCRoot或引用计数算法计算出存活的对象拷贝至Survivor To区然后清理Eden和Survivor From区之后将Survivor To和Survivor From互换,并将存活的对象"年龄"加一,当有对象年龄大于等于15(默认可配)时转移到老年区。
2.1.1、引用计数
不好解决循环依赖的对象
2.1.2、GCRoot
从“GC Roots”对象开始向下搜索,如果一个对象引用链上,说明该对象可以被回收。“GC Roots”对象包括:
- 虚拟机栈中局部变量表中引用的对象
- 方法区中类的静态变量、常量引用的对象
- 本地方法栈中 JNI (Native方法)引用的对象
程序计数器: 用来表示当前执行的是哪条指令
局部变量表: 用来存放当前执行方法的局部变量的值
操作数栈: 用来执行操作命令
动态链接: 将符号引用转化为直接引用的过程。因为在编译时,java类并不知道所引用的类的实际地址,因此只能使用符号引用来代替。
方法出口: 记录方法调用者的引用
执行引擎
GC算法
1、标记清除算法
标记需要清除的对象后清除。
劣势:时间效率低;空间碎片化。
2、复制算法
保留一块大小相同的内存区域,将保留的内存复制到未启用的区域后清空原区域。新生代的算法。
3、标记整理算法
标记需要清除的对象后清除完成之后进行整理。老年代的算法。