写点什么

JVM 知识整理

发布于: 5 小时前

一,jvm 基础知识

Java 是一种面向对象的、静态类型、编译执行,有 vm/GC 和运行时、跨平台的高级语言。


字节码、类加载器、虚拟机内存

jvm 通过类加载器加载字节码到虚拟机内存


类加载器

启动类加载器

jvm 最核心的 jar 包和类,比如 String 和 Object,它是所有应用程序都需要使用的类


扩展类加载器

负责给 jvm 加载一些额外的类,比如我们在目录里额外放一些 jar 包


应用类加载器

负责加载我们自己的代码生成的类以及依赖项


为什么要有这个区分


1、双亲委托

2、负责依赖

3、缓存加载


jvm 内存模型

方法中使用的原生数据类型和对象引用地址在栈上存储

对象、对象成员与类定义、静态变量在堆上


堆内存又称为"共享堆",堆中的所有对象,可以被所有线程访问,只要

他们能拿到对象的引用地址


如果两个线程同时调用某个对象的同一方法,则它们都可以访问到这个对象的成员变量,

但每个线程的局部变量副本是独立的


jvm 启动参数

1 系统属性参数

2 运行模式参数

3 堆内存设置参数

4 GC 设置参数

5 分析诊断参数

6 JavaAgen 参数


GC 背景与一般原理


为什么会有 GC

本质上是内存资源的有限性

因此需要大家共享使用,手工申请,手动释放


如果你自己去设计对象回收机制怎么设计

通过一个仓库的例子

有人使用就+1,不用了就登出


实际情况复杂一点

仓库与仓库之间也有关系

如果是一个环的话,大家的计数永远不为 0,会导致内存泄漏-》内存溢出

这个地方跟事务的死锁是一个道理


改进:引用计数-〉引用跟踪


那既然采用了引用跟踪,我们就要想它有什么算法 -》标记清除算法,它是并行 GC 和 CMS GC 的基本原理


标记:遍历所有的可达对象,并在本地内存中分门别类记下

清除:这一步保证了,不可达对象所占用的内存,在之后进行内存分配时可以重用


它的优势就是对于饮用计数的循环依赖问题是可以解决的,因为它只跟踪可达的对象,就算形成了一个环,但是如果都是不可达的,那么在引用跟踪也会清除


除了清除还要做压缩,就是碎片整理


怎么才能标记和清除上百万对象,答案就是 STW,让全世界停下来

怎么理解 STW,就是一个阿姨打扫屋子的案例,很多人在屋子里走来走去,要打扫屋子了,就让他们先出去

对象分配在新生的 Eden 区域

标记阶段 Eden 区存活的对象就会复制到存活区


注意:为什么是复制,不是移动

两个存活区 from 和 to,互换角色。

对象存活到一定周期会提升到老年代

由参数控制提升阈值


老年代默认都是存活对象,采用移动方式

1.标记所有通过 GC roots 可达的对象

2 删除所有不可达对象

3 整理老年代空间中的内容,方法是将所有的存活对象复制,从老年代空间

开始的地方依次存放


新生代

发生 minor gc 时,用的是标记复制算法


java 新生代为什么要有两个 survivor 区

1)survivior 存在的意义就是做一个预筛选,减少被送到老年代的对象,进而减少 FULLGC 的发生

2)设置两个 survivor 区最大的好处就是解决了碎片化


串行 GC

Serial GC


并行 GC

Parallel GC

jdk6,7,8 默认都是并行 GC,再之上的版本 9 以后都是 G1


CMS GC

设置目标是避免在老年代垃圾收集时出现长时间的卡顿


还是阿姨打扫房间的例子,并行 GC 就是先让人出去,多个阿姨打扫房间。

CMS GC 就是先不用出去,让出 1/4 的空间,我们一块儿一块儿的打扫


六个阶段

1)初始标记

2)并发标记

3)并发预清理

4)最终标记

5)并发清除

6)并发重置

重置 CMS 算法相关的内部数据,为下一次 GC 循环做准备


CMS 优缺点

最大的问题就是老年代内存碎片问题


G1 GC

G1 GC 最主要的设计目标是:将 STW 停顿的时间和分布,变成预期且可配置的

G1 GC 堆不再分成年轻代和老年代,而是划分为多个小块,每个小块可能一会被定义成 Eden 区,

一会被指定为 Survivor 区域、或者 Old 区


ZGC

java11 引入


Shenandoah GC

java12 引入


用户头像

优秀工程师 2020.06.14 加入

-热爱编程 -热爱生活 -无所畏惧

评论

发布
暂无评论
JVM知识整理