Skip to content

Latest commit

 

History

History
95 lines (62 loc) · 4.92 KB

Java 垃圾回收算法与日志分析.md

File metadata and controls

95 lines (62 loc) · 4.92 KB

Java 垃圾回收算法与日志分析

Stop The World:

​ GC 过程中分析对象引用关系,为了保证分析结果的准确性,需要通过停顿所有 Java 执行线程,保证引用关系不再动态变化,该停顿事件称为 Stop The World(STW)。

Safepoint:

​ 代码执行过程中的一些特殊位置,当线程执行到这些位置的时候,说明虚拟机当前的状态是安全的,如果有需要 GC,线程可以在这个位置暂停。HotSpot 采用主动中断的方式,让执行线程在运行期轮询是否需要暂停的标志,若需要则中断挂起。

一、标记-清除算法(标记阶段+清除阶段)

碎片化,造成内存不连续

二、复制算法

  • 将可用内存分为对象面和空闲面—>
  • 对象在对象面上创建—>
  • 存活的对象被从对象面复制到空闲面—>
  • 将对象面所有对象内存清除。

​ 解决了碎片化问题,简单高效适用于对象存活率低的场景,不适合对象存活率高的场景,会进行大量复制操作 可用空间减半。

三、标记-整理算法

  • 标记阶段: 从根集合进行扫描,对存活的对象进行标记
  • 整理阶段: 移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收
优点:
  • 避免内存的不连续行
  • 不用设置两块内存互换
  • 适用于存活率高的场景

四、分代收集算法(垃圾回收算法的组合拳)

​ 按照对象生命周期的不同划分区域以采用不同的垃圾回收算法。能够明显提高提高JVM的回收效率。分代收集算法将内存区域分为年轻代、老年代(JDK8开始取消永久代,使用元空间代替)并使用不同的GC进行垃圾回收。

年轻代(占总堆内存的三分之一、复制算法):

  • 将内存区域进一步划分为 Eden 区,和2个 Survivor 区
  • Eden GC 时,将存活对象复制到 Survivor1 中,Survivor1 GC 时将存活对象复制到 Survivor2 中
  • 采用 Minor GC
  • 尽可能快速地收集掉那么些生命周期短的对象
  • 年轻代对象可以晋升到老年代

老年代(占总堆内存的三分之二):

  • 存放生命周期较长的对象
  • 使用 Full GC(标记清理算法或者标记整理算法)
  • 老年代GC时,会触发对整个堆内存的垃圾回收
年轻代对象如何晋升到老年代:
  • (1)经历一定 Minor GC 次数 依然存活的对象
  • (2)Survivo 区中存放不下的对象
  • (3)新生成的大对象 (-XX:+PretenuerSizeThreshold)
触发Full GC的条件:
  • (1)老年代空间不足
  • (2)永久代空间不足(jkd 8 之前)
  • (3)CMC GC 时 出现 promotion failed, concurrent mode failure
  • (4)Minor GC 晋升到老年代的平均大小大于老年代的剩余空间
  • (5)调用 System.gc()[通知JVM进行垃圾回收,但要注意,虽然发出了通知,JVM不一定会立刻执行,也就是说这句是无法确保此时JVM一定会进行垃圾回收的]
  • (6)使用 RMI 来进行 RPC 或管理的 JDK 应用,每小时执行1次 Full GC

五、finalize()方法:

​ Java GC 时会对对象做两次标记, 第一次标记, 判断对象是否要执行 finalize() 方法,如果需要执行,就将对象放置于 F-Queue 队列中,并在稍后由虚拟机创建的一个低优先级的线程触发执行该对象的 finalize() 方法。该方法执行随时可能被终止,作用是给予对象最后一个重生的机会。

六、日志分析

​ GC 日志是一个很重要的工具,它准确记录了每一次的 GC 的执行时间和执行结果,通过分析 GC 日志可以调优堆设置和 GC 设置,或者改进应用程序的对象分配模式,开启的 JVM 启动参数如下:

Young GC:

GC开始时间 +0800 表示中国所在东8区    GC开始时间相对JVM开始启动时间间隔秒数  GC 表示 Young GC+触发原因 
--2019-12-20T17:49:34.558+0800:   1.332:                        [GC (Allocation Failure) 

垃圾收集器名称  垃圾收集前后新生代使用量/新生代总空间大小    垃圾收集前后整个堆的内存使用量/堆总空间大小  GC 事件持续时间
--[PSYoungGen: 65536K->5886K(76288K)]                    65536K->5894K(251392K),                    0.0071360 secs] 
GC线程消耗CPU的时间/操作系统调用和系统等待事件锁消耗的时间/应用程序暂停的时间
--[Times: user=0.00 sys=0.00, real=0.01 secs] 

OLD GC:

--2019-12-20T17:49:35.425+0800: 2.200: [Full GC (Metadata GC Threshold) [PSYoungGen: 5762K->0K(141824K)] 
--[ParOldGen: 104K->5727K(77824K)] 5866K->5727K(219648K), [Metaspace: 21122K->21121K(1069056K)], 0.0217453 secs] [Times: user=0.06 sys=0.03, real=0.02 secs]

免费的 GC 日志图形分析工具:GCViewer 和 gceasy 。