JVM详解-从入门到深入了解

之前很长一段时间都在学习JVM,但是因为时间断断续续,再加上没有经常性的使用,导致看过就忘,最近有重新复习了一遍,但是相比刚开始的时候,还是有了更好的了解。啰嗦那么多就是想告诫自己-- 熟能生巧,理论+实践。

Java Virtual Machine

About JVM

  • 内存划分

|center

  • 堆内存分配

    VM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指 定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。

    | 组成 | 详解|
    | ------| :------: |
    |Young Generation | 即图中的Eden + Survivor (From Space + To Space)|
    | Eden|存放新生的对象,也是主要对象存放位置|
    |Survivor Space|有两个,存放每次垃圾回收后存活的对象,总会存在一个为空|
    |Old Generation| Tenured Generation 即图中的Old Space 主要存放应用程序中生命周期长的存活对象|

About GC

对象存活
  • 引用计数
    对象新增一个引用,那么计数增1.
  • 可达性分析
    从GC roots 开始向下搜索,经历的链路成为引用链,没有被引用链关联的引用,为不可用对象。

Java中GC Roots:

  1. 虚拟机栈中引用的对象。
  2. 方法区中静态属性引用的对象。
  3. 方法区中常量引用的对象。
  4. 本地方法栈中JNI引用的对象。
GC 算法
  • Mark-Sweep 标记-清除

    缺点: 效率较低;碎片化严重。

  • Copy 复制算法

缺点: 持续复制,效率低。

  • Mark-Compact 标记-压缩(老年代使用)
GC Collectors
  • Serial

有点古老,串行收集,在多cpu,多core的今天,已经渐渐被淘汰:

参数控制: -XX:+UseSerialGC

  • ParNew

Serial 的多线程版本,新生代并行,复制算法,老年代串行,标记-压缩算法。

参数控制: -XX:+UseParNewGC; -XX:ParallelGCThreads 线程数量。

  • Parallel Scavenge

类似ParNew,他关注的系统的吞吐量,也可以通过参数实现自适应性调节控制。新生代复制算法,老年代标记-压缩算法。

  • Parallel Old

since jdk 1.6

多线程 + 标记-整理算法

参数控制: -XX:+UseParallelOldGC

  • CMS Concurrent Mark Sweep

一种以最短停顿为目标的收集器

  • 初始标记(initial mark) stop-the-world,标记gc roots 直接关联对象。
  • 并发标记(concurrent mark)trace gc roots
  • 重新标记(remark) stop-the-world
  • 并发清除(concurrent sweep)

优点:并发收集,低停顿;
缺点:大量碎片;并发阶段;

参数控制: -XX:+UseConcMarkSweepGC,-XX:+ UseCMSCompactAtFullCollection 在Full GC后,进行一次碎片整理;整理过程是独占的,会引起停顿时间变长.

  • Garbage First
  1. 空间整合,G1收集器采用标记整理算法,不会产生内存空间碎片。分配大对象时不会因为无法找到连续空间而提前触发下一次GC。

  2. 可预测停顿,这是G1的另一大优势,降低停顿时间是G1和CMS的共同关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为N毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。

内存分为多个大小相等的独立区域(Region)

  • 收集步骤:
  1. 标记阶段,首先初始标记(Initial-Mark),这个阶段是停顿的(Stop the World Event),并且会触发一次普通Mintor GC。对应GC log:GC pause (young) (inital-mark)。

  2. Root Region Scanning,程序运行过程中会回收survivor区(存活到老年代),这一过程必须在young GC之前完成。

  3. Concurrent Marking,在整个堆中进行并发标记(和应用程序并发执行),此过程可能被young GC中断。在并发标记阶段,若发现区域对象中的所有对象都是垃圾,那个这个区域会被立即回收(图中打X)。同时,并发标记过程中,会计算每个区域的对象活性(区域中存活对象的比例)。

  4. Remark, 再标记,会有短暂停顿(STW)。再标记阶段是用来收集 并发标记阶段 产生新的垃圾(并发阶段和应用程序一同运行);G1中采用了比CMS更快的初始快照算法:snapshot-at-the-beginning (SATB)。

  5. Copy/Clean up,多线程清除失活对象,会有STW。G1将回收区域的存活对象拷贝到新区域,清除Remember Sets,并发清空回收区域并把它返回到空闲区域链表中。

  6. 复制/清除过程后。回收区域的活性对象已经被集中回收到深蓝色和深绿色区域。

About Monitor

jstat

HotSpot JVM 提供的一个监控工具,不仅提供GC操作的信息,还有提供类装载操作的信息以及运行时便已操作对的信息。

  • 使用方法 -> jstat -[option] [other-option] [interval] [times] ; 【jvmId】的获取 ps -ef | grep java
  • 输入参数 option
参数描述
gc输出每个堆区域的当前可用空间以及已用空间(Eden,Survivor等等),GC执行的总次数,GC操作累计所花费的时间。
gccapacity输出每个堆区域的最小空间限制(ms)/最大空间限制(mx),当前大小,每个区域之上执行GC的次数。(不输出当前已用空间以及GC执行时间)。
gccause输出-gcutil提供的信息以及最后一次执行GC的发生原因和当前所执行的GC的发生原因
gcnew输出Young的GC性能
gcnewcapacityYoung空间大小的统计
gcoldOLD 空间GC性能
gcoldcapacityOLD空间大小的统计
gcpermcapacityperm大小的统计
gcutil输出每个堆区域使用占比,以及gc执行的总次数和GC操作所花费的时间
  • 输出数据介绍 :

  • S0/S1/E/O/P [C/U] - 对应区域的空间大小和使用量,单位KB,

  • YGC/FGC[-/T] - GC的统计次数、时间

  • NGC/OGC/PGC[/MN/MX] 对应区域当前大小/最小值/最大值

  • GCC/LGCC 当前/最后一次GC的原因

  • TT 老年化阈值,在移动向老年代之前,能够在新生代存活次数。

  • MTT 最大老年化阈值,同上。

  • DSS 幸存者所需要的空间大小,单位KB

其中:
C - capacity 空间大小
U - used 使用量
T - 对应GC时间

  • other-option

  • -hn 展示每次输出数据的前n行。 -h3 只显示前3行。

后面会持续更新,并不断的回顾且加以实践。


----2019年03月25更新----

补充问题
  • CMS 中的初始标记阶段是否为单线程?为什么?
  • CMS 缺点的具体表现是什么?
  • 9
    点赞
  • 126
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值