JVM读书笔记

143 阅读5分钟

一.类加载过程

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的靶心,基本是干活。这篇大部分的读书笔记都是来自【公众号:楼仔】