深入理解jvm

深入理解jvm

1.类加载机制

通过javac编译成class文件 通过类加载器 加载到jvm虚拟机,方法区里面放二进制数据,堆区里面class对象

加载步骤

加载->验证->准备->解析->初始化

类加载器

根加载器->扩展类加载器->应用加载器加载->自定义加载器

一般采用的双亲委派机制,先判断自己有没有加载过这个class,然后让父加载器加载,一直向上委托,直到委托到根加载器,然后再判断自己能否加载;如果不能就向下委托,让子加载器加载,直到class被加载;这样可以避免重复加载,热部署就是跳过双亲委派机制,重复加载类。

2.内存模型

  1. new的对象就放在堆,jvm内存调优也是优化这个内存

    • 新生代 eden区 survivor1 survivor2
    • 老年代
  2. 在线程执行方法的时候,会栈开辟一个栈帧,一般用于存放方法的局部变量之类的,栈帧遵循先进后出

  3. 本地方法栈

    存放一个c++写的本地方法

  4. 程序技术器

    来记录线程执行代码到那一行,在线程上下文切换的时候就知道从那一行代码来执行

  5. 方法区

    用来存放常量、静态变量和类信息

2.1堆

当eden区被放满,就会发生样gc,然后把未回收的对象放在survivor1区;当eden区再次被放满,再次发生养gc,把eden区和survivor1区的垃圾对象回收,剩下的对象放在survivor2区,对象分代年龄达到一次次数,会被放入老年代;如果老年代满了,会发生负gc,所以线程会被停止,等待垃圾回收完成。

在样gc之前,会判断年轻代所有的对象大小是否大于老年代剩余空间,同时没有开启担保配置,那么会直接负gc,如果开启了担保配置,那么还会判断判断老年代剩余空间是否小于年轻代每次样gc后放入老年代对象的平均大小,如果小于会直接发生负gc;之后在做样gc效率会高很多,也就是说jvm判断样gc后大概率还要负gc,那么先负gc再样gc效率更高

  • 大对象到达到一定大小直接进入老年代

  • 分代年龄达到一定数量会进入老年代

  • 如果有一批对象放在survivor区,总量大小超过survivor区的百分之50,会被直接放到老年代

3.垃圾收集器

3.1gc垃圾回收算法

如何判断是否回收对象

  • 引用计数法

    对象每引用一次就会+1,释放了就-1,计数值为0就代表是垃圾对象可以回收;但是如果a引用b,b引用a,就会导致他的值永远为1

  • 可达性分析(目前jvm使用这种方式)

    通过gc root的引用链路来判断,在这个链路上的都是非垃圾对象

gc算法

标记清除,先扫描,把需要删除的标记上,扫描完后,清除, 会产生空间碎片

标记整理,删除后会移动,不会产生碎片,

复制删除,有两个空间,把不需要删除的对象移到第二个空间,然后直接把第一个空间的删除

3.2垃圾收集器种类

串行(年轻代-复制删除/老年代-标记整理)

就是在负gc的时候单线程执行,速度慢,用户线程等待时间长

并行(年轻代-复制删除/老年代-标记整理)

负gc的时候多线程执行。

prenew(年轻代-复制删除)

也是多线程执行,主要配合cms使用,prenew负责年轻代,cms负责老年代

cms(老年代-标记清除 也可以通过参数进行整理空间)

初始标记:单线程或者多线程,标记初始的gc root 这个过程很短,会中止用户线程

并发标记:多线程进行并发标记,通过gc root引用链路往下找,不会中止用户线程,这个过程最耗时间,会存在期间用户线程产生新的垃圾对象,这种只能等下次负gc清理

重新标记:重新标记一遍,主要处理漏标的问题,会中止用户线程,但是处理时间远远小于并发标记

并发清理:清理未标记的对象,不会中止用户线程,期间产生的用户线程会标记成黑色不做处理。

重置标记:清理重置标记记录

cms不是在老年代内存到达百分之百才触发负gc,而是默认达到百分之92触发,需要预留一些空间,防止并发失败,从而切换成串行负gc

G1:

初始标记:中止业务线程,记录gc root直接能引用的对象。

并发标记:不会中止业务线程,从过cg root的对象引用链路往下找,这个过程最耗时,但不影响业务。

重新标记:中止业务线程,主要处理漏标的问题。

筛选回收:会根据配置的停顿时间来清理,也就是如果配置了200m,那么会中止业务线程200m,剩下没有回收的等下次;还会根据清除时间对区域排序清除。

将堆内存分为很多小区域,然后老年代年轻代都是采用的标记复制法,还多了一个humongous区专门放大对象,然后负gc会把年轻代和老年代humongous区全部收集回收。

ZGC

初始标记:中止业务线程,记录gc root直接能引用的对象。

并发标记:不会中止业务线程,从过cg root的对象引用链路往下找,这个过程最耗时,但不影响业务。

重新标记:中止业务线程,主要处理漏标的问题。

并发转移准备:根据清除时间对区域排序

初始移动:把会gcroot 直接引用的对象 且标记的对象,先用标记复制法移动,这个过程会stw。

并发移动:通过gc root的引用链路把其他标记的对象移动过来,这个过程不会stw。

zgc把内存分为小中大三种分页,大对象一般放入中页或者大页,一般都是会小页进行gc,zgc只会在初始标记、重新标记、初始移动的时候stw,大大减少了stw的时间,一般stw时间只需要1m。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值