JDK、JRE、JVM

jdk是开发人员用的开发工具包,包括jre
jre是java运行环境,提供了库、JVM等工具,用于运行Java程序
jvm负责将java程序生成的字节码文件变成机器语言执行。

client、server模式

在jvm中有两种运行模式:client和server
client模式加载速度快,用于GUI交互程序
server模式加载速度慢,但运行较快,用于服务器后台等程序。

JVM类加载

加载->链接->初始化->使用->卸载
加载:JVM可从文件系统读取、从JAR压缩包提取、也可网络下载、数据库加载、运行时生成等。
链接:包括三个阶段。

  • 验证:确保被加载类的正确性,验证字节流是否符合class文件规范
  • 准备:为类的静态变量分配内存并设置初始值
  • 解析:解析包括常量池数据和属性表信息,包括ConstantPool结构体和AttributeInfo接口等。

初始化:为标记常量值的字段赋值,以及执行方法。
使用:程序执行使用。
卸载:程序代码退出、异常、结束等。
加载机制:

  1. 全盘负责:当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入
  2. 父类委托:先让父类加载器试图加载该类,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类
  3. 缓存机制:缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区寻找该Class,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效

    JVM内存模型

    image.png

    程序计数器

    线程私有、记录当前线程执行的字节码行号、如果执行java方法,计数器记录虚拟机字节码当前指令的地址,本地方法则为空。

    Java虚拟机栈

    每个方法在执行的同时,会创建一个栈帧,用于存放局部变量表、操作数栈、动态链接、方法出口、线程等信息。
    方法从调用到执行完成,对应栈帧从虚拟机中入栈和出栈的过程。
    方法结束后栈帧被摧毁。

    本地方法栈

    作用与Java虚拟机栈类似,但是执行的是Native方法。

    堆和元空间

image.png
Java堆是内存空间占据最大的部分。由青年代和老年代组成。
元空间在本地内存,仅受本地内存的限制,不会因为永久代空间不够而抛出oom异常。

GC垃圾回收

对象死亡判断

引用计数器

为对象添加引用计数器,统计指向对象的引用次数,当对象的引用计数器为0时,可以进行回收。
缺点:循环依赖导致的内存泄露。

可达性分析法

穷举GC Roots引用的对象填充到集合,只标记存活对象。
GC Roots包括:
全局性引用
执行上下文
已启动且未停止的Java线程
缺点:
误报:已死亡对象标记为存活
漏报:引用的对象没有被标记为存活,会导致JVM崩溃

垃圾回收算法

标记清除算法

无引用的死亡对象记录到空闲表中
缺点:内存碎片化严重

标记复制算法

将内存区分为两个部分from和to,from指向分配内存区域,当GC时把存活对象复制到to,然后交换from和to指针。
缺点:浪费一半堆空间。

标记压缩算法

清除完了向一段移动。
缺点:开销较大

垃圾回收器

新生代

  1. Serial 标记复制 Client模式下默认新生代收集器
  2. Parallel ParNew 标记复制
  3. Parallel Scavenge 标记复制

    老年代

  4. Serial Old 标记压缩

  5. Parallel Old 标记压缩
  6. CMS 标记清除

    G1

    标记压缩算法
    适用于多核大内存机器,GC多线程并行执行,低停顿高回收率