JVM构成

走进JVM的世界

JVM构成

  1. 堆(Heap)
  2. JVM栈
  3. 本地方法栈
  4. 程序计数器
  5. 元空间(JDK8之前为Perm区 永生代区)

1. 堆(Heap)

1.1 简介
  1. 存储着几乎所有的实例对象,发生OOM最主要的发源地。
  2. 由垃圾回收器自动回收,各个子线程共享

1.2 参数调整

可以添加JVM参数对堆区大小进行指定

  1. -Xms xxxM (memory start)
  2. -Xmx xxxM (memory max)

为了避免堆空间频繁的扩容回缩,一般Xms和Xms设置成一样的大小


1.3 堆被划分为
  1. 新生代区域
  2. 老年代区域

其中 新生代分为

  1. Eden区
  2. Survivor区

其中 Survivor区 又分为S0/S1两个区域

为什么要设置两个Survivor区?

没有Survivor区,eden区对象直接去老年代,造成老年代频繁FGC。
一个Survivor容易使得Survivor的空间碎片化,因为eden区又存活对象,Survivor区也有存活对象,辅助的时候就会存在碎片化空间。
即若只分一块Survivor,在清除Survivor区已死亡的对象时,因为此刻的Survivor区还有存活的对象,清除要比分两块Survivor麻烦,两块的情况,回收时只需将存活的对象移走,剩下的对象直接清理即可。
另外,分成两块Survivor,From和To分工明确,逻辑理解和技术实现较简单。


1.4 内存申请流程
  1. 内存申请
  1. 先到Eden区申请内存空间 如果申请成功 则分配成功
  2. 申请失败会触发一次Young Garbage Collection即 YGC
  3. 再次去Eden区申请 如果申请成功 则分配成功
  4. 申请老年代区域内存空间 如果申请成功 则分配成功
  5. 触发一次Full Garbage Collection即 FGC
  6. 再次申请老年代内存空间 如果申请成功 则分配成功 申请失败则发生OOM

  1. YGC
  1. 旧对象是否能够在Survivor区存储 如果过放得下,未超过存活阈值,则放置在S0/S1区,并且计数器+1
  2. 如果放不下或者超过对象存活阈值晋升至老年代

  1. 流程图
  1. 内存申请
    申请内存空间流程图

  1. YGC
    YGC流程图

  1. FGC

用于清理整个堆空间。


  1. JVM参数
  1. -XX:MaxTenuringThreshold 调整新生代转至老年代的存活阈值
  2. -XX:+HeapDumpOnOutOfMemoryError JCM遇到OOM输出堆内信息

2.JVM栈

2.1 简介

JVM栈是描述方法执行的内存区域 线程私有
包含局部变量表、操作栈、动态链接、方法返回地址4个部分
位于栈顶的帧才是有效的,称为当前栈帧。
栈帧是方法运行的基本结构。
是发生StackOverFlow的区域。(递归调用导致JVM栈内存溢出)


2.2 局部变量表

输入参数和输出参数以及方法内的变量


2.3 操作栈

记录出栈、入栈的操作


2.4 动态链接

每个栈帧中包含一个在常量池中对当前方法的引用,目的是支持方法调用过程的动态连接


2.5 方法返回地址

执行过程中成功或异常需执行的字节码指令

3.本地方法栈

与操作系统交互相关的操作


4.程序计数器

  1. 简介

程序计数器的作用是在一些指令的执行过程中, 记住下一条JVM指令的执行地址。

  1. 特点
  1. 线程私有
  2. 不会出现内存溢出

5.元空间

  1. 简介

存储包括类元信息、字段、静态属性、方法、常量等信息

  1. 升级历史

jdk8之前永生代存储在JVM中的方法区来进行垃圾回收 JDK8之后元空间取代了方法之前的方法区
并且将永生代中的常量池,静态变量并入堆内


6.垃圾回收

  1. 简介

垃圾回收的主要目的是清除不再使用的对象,自动释放内存

  1. 哪些对象会被垃圾回收

现代虚拟机基本都是采用可达性分析算法来判断对象是否存活,可达性算法的原理是以一系列叫做 GC Root 的对象为起点出发,引出它们指向的下一个节点,再以下个节点为起点,引出此节点指向的下一个结点。这样通过 GC Root 串成的一条线就叫引用链),直到所有的结点都遍历完毕,如果相关对象不在任意一个以 GC Root 为起点的引用链中,则这些对象会被判断为垃圾对象,会被 GC 回收。


6.1 垃圾回收器

Serial

  1. 执行YGC时使用Mark-copy算法,执行FGC时采用标记-整理算法
  2. 特点:主要应用于YGC,串行执行回收,影响程序运行会产生Stop The World(STW) FGC触发会长时间影响程序运行

CMS

  1. 执行流程: 初始标记->并发标记->重新标记->并发标记
  2. 由于CMS采用标记-清除算法,因此会产生大量内存空间碎片。为了解决这个问题可以配置JVM在执行FGC后对老年代进行压缩,执行一次空间整理,整理阶段也会触发STW。为了减少STW次数还可以配置在N次FGC后再执行碎片整理。
  3. 特点: 目前较常用的垃圾回收器
  4. JVM参数调整:
  1. -XX:+UseCMSCompactAtFullCollection 调整FGC后强制执行空间整理
  2. -XX:+CMSFullGCsBeforeCompaction=n n次FGC后执行空间整理

G1

  1. 简介

G1将内存空间分割成了若干相同大小的区域,即region,包括Eden,Survivor,Old,Humongous四种类型
其中Humongous专门用来存储大型对象
这样做的好处是不需要连续的内存空间来管理对象
G1将内存内存划分为多个区域,优先回收垃圾最多的区域

  1. 特点:
  1. G1采用Mark-Copy算法有非常好的内存整合能力,不会产生大量的内存碎片。
  2. 并发处理垃圾
  1. 执行流程:
  1. Initial Mark 其实就是YGC。该阶段会引起STW,标记GC Roots直接可达的存活对象
  2. Root Region Scan 根区域扫描,该阶段不会STW,它会并发的从上一阶段标记的存活区域中扫描被引用的老年代对象。
  3. Concurrent Mark 并发标记。该阶段从堆中标记存活的对象。
  4. Remark 重新标记 该阶段会引起STW 完成最终的标记处理
  5. Cleanup 主要为接下来的Mixed GC作准备。该阶段会统计所有堆区域的存活对象,并将待回收的区域进行回收价值排序,优先回收垃圾最多的区域。

6.2 垃圾回收算法
  1. 标记-清除
  1. 简介

该算法分为标记和清除两个阶段。标记就是把所有活动对象都做上标记的阶段;清除就是将没有做上标记的对象进行回收的阶段。

  1. 特点
  1. 实现简单
  2. 由于分配一个较大的连续空间时容易触发FGC,会产生大量的内存空间碎片
  1. 标记-复制
  1. 简介

复制算法就是将内存空间按容量分成两块。当这一块内存用完的时候,就将还存活着的对象复制到另外一块上面,然后把已经使用过的这一块一次清理掉。这样使得每次都是对半块内存进行内存回收。内存分配时就不用考虑内存碎片等复杂情况,只要移动堆顶的指针,按顺序分配内存即可,实现简单,运行高效。

  1. 标记-整理

与标记-清理算法类似,后续清除阶段为将存活的对象移动到一端,形成连续的内存空间,然后清除掉边界以外的内存。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值