【学习笔记】JVM相关

对象的创建过程

1. class loading

2. class linking (verification, preparation, resolution)

  • Verfication:验证文件是否符合JVM规定
  • Preparation:静态成员变量赋默认值
  • Resolution:将类、方法、属性等符号引用解析为直接引用

3. class initializing:调用类初始化代码,给静态成员变量赋初始值

4. 申请对象内存

5. 成员变量赋默认值

6. 调用构造方法<init>

  • 成员变量顺序赋初始值
  • 执行构造方法语句

普通对象

1. 对象头:markword 8

2. ClassPointer: -XX: +UseCompressedClassPointers为4字节,不开启为8字节

3. 实例数据  引用类型: -XX: +UseCompressedOops为4字节,不开启为8字节

4. padding对齐,8的倍数

数组对象

1. 对象头:markword 8

2. ClassPointer指针同上

3. 数组长度:4字节

4. 数组数据

5. padding对齐 8的倍数

markword 64位

1. hashCode部分

31位hashcode -> System.identityHashCode

按原始内容计算的hashcode,重写过的hashcode方法计算的结果不会存在这里。

无用的类:

1. 该类所有的实例都已经被回收,Java堆中不存在该类的任何实例。

2. 加载该类的ClassLoader已经被回收。

3. 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

GC垃圾回收的原理:判断出死亡的对象,然后清除死亡的,留下存活的。

  • 引用计数法(Reference Counting)
  • 可达性分析算法(Reachability Analysis)

通过"GC Roots"对象(线程栈变量、静态变量、常量池、JNI指针)作为起始点,然后从这些节点开始遍历所有引用链。如果某个对象没有GC Roots直接或间接连接的话,这个对象就被认为程序中不再使用可以被回收了。

垃圾回收的几种算法

  • 标记清除

算法相对简单 存活对象比较多的情况下效率较高

两遍扫描,效率偏低 容易产生碎片

  • 标记复制

适用于存活对象较少的情况,只扫描一次,效率提高,没有碎片

空间浪费,移动复制对象,需要调整对象引用

  • 标记压缩

不会产生碎片,方便对象分配,不会产生内存减半

扫描两次,需要移动对象,效率偏低

程序计数寄存器(Program Counter Register),JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟。

  • PC寄存器用来存储指向下一条指令的地址,即将要执行的指令代码。由执行引擎读取下一条指令。
  • 在JVM规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程周期一致。

每个线程在创建的时候都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应一次次Java方法调用,是线程私有的,生命周期和线程一致。

作用:主管Java程序的运行,它保存方法的局部变量,部分结果,并参与方法的调用和返回。

Method Area

  • Perm Space (<1.8) 字符串常量位于Perm Space FGC不会清理 大小启动的时候指定,不能变
  • Meta Space (>=1.8) 字符串常量位于堆 会触发FGC清理 不设定的话,最大就是物理内存

JVM内存分代模型(用于分代垃圾回收算法)

  • 部分垃圾回收器使用的模型

除Epsilon ZGC Shenandoah之外的GC都是使用逻辑分代模型

G1是逻辑分代,物理不分代

除此之外,不仅逻辑分代,而且物理分代

MinorGC/YGC: 年轻代空间耗尽时触发

MajorGC/FullGC: 在老年代无法继续分配空间时触发,新生代老年代同时进行回收

  • 栈上分配

线程私有小对象

无逃逸

支持标量替换

无需调整

  • 线程本地分配TLAB (Thread Local Allocation Buffer)

占用eden,默认1%

多线程的时候不用竞争eden就可以申请空间,提高效率

小对象

无需调整

对象分配过程

垃圾回收器

JDK1.8默认的垃圾回收:PS + ParallelOld

Serial: a stop-the-world, copying collector which uses a single GC thread

CMS的问题

1. Memory Fragment

2. Floating Garbage

算法:

CMS算法:三色标记 + Incremental Update

G1算法:三色标记 + SATB

ZGC算法:ColoredPointers + 写屏障

Shenandoah算法:ColoredPointers + 读屏障

调优系统CPU占用率100%

一定有线程在占用系统资源

  1. 找出哪个进程CPU高(top)
  2. 该进程中的哪个线程CPU高(top -Hp)
  3. 导出该线程的堆栈(jstack)
  4. 查找哪个方法(栈帧)消耗时间(jstack)

查找系统内存飚高问题

  1. 导出堆内存(jmap)
  2. 分析(jhat, jvisualvm, mat, jprofiler ...)

三色标记

  • 白色:未被标记的对象
  • 灰色:自身被标记,成员变量未被标记
  • 黑色:自身和成员变量均已标记完成

产生漏标

1. 标记进行时增加了一个黑到白的引用,如果不重新对黑色进行处理,则会漏标

2. 标记进行时删除了灰对象到白对象的引用,那么这个白对象有可能被漏标

1. incremental update: 增量更新,关注引用的增加,把黑色重新标记为灰色,下次重新扫描属性(CMS)

2. SATB(snapshot at the beginning):关注引用的删除 当引用消失时,把这个引用推到GC的堆栈,保证D还能被GC扫描到(G1)

灰色 -> 白色引用消失时,如果没有黑色指向白色引用会被push到堆栈,下次扫描时拿到这个引用,由于有RSet的存在,不需要扫描整个堆去查找指向白色的引用,效率较高。

CMS执行步骤:初始标记、并发标记、重新标记、并发清理

G1产生FGC怎么做

1. 扩内存

2. 提高CPU性能(回收的快,业务逻辑产生对象的速度固定,垃圾回收越快,内存空间越大)

3. 降低MixedGC触发的阈值,让MixedGC提早发生(默认是45%)

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值