JVM:垃圾回收机制和调优手段--1

引言: 我们都知道JVM内存由几个部分组成: Java栈、程序计数器(ProgramCounter)寄存器、本地方法栈、堆、方法区、运行常量池。 JVM垃圾回收仅仅针对公共内存区域即:堆和方法区进行。 本...

引言:

我们都知道JVM内存由几个部分组成 Java栈、程序计数器(ProgramCounter)寄存器、本地方法栈、堆、方法区、运行常量池。

JVM垃圾回收仅仅针对公共内存区域即:方法区进行。

本文主要讨论两点,一是垃圾回收策略,二是调优的方法。

一、垃圾回收机制1.1 分代管理

方法区按照对象出现的不同时间进行分代:

u  堆中会频繁地创建对象,基于一种分代的思想,按照对象存活时间将划分为新生代旧生代两部分,我们不能一次垃圾回收新生代存活的对象就放入旧生代,而是要经过几次GC后还存活的对象,我们才放入旧生代,所以我们又把新生代再次划分为Eden区和两个Survivor区,让对象创建在Eden区,然后在两个Survivor之间反复复制,最后仍然存活的对象才复制到旧生代中。

u  方法区存放的是常量、加载的字节码文件信息等,信息相对稳定。因为不会频繁地创建对象,所以不需要分代,直接GC即可。

由此我们JVM垃圾回收要扫描的范围是:

attachments-2016-09-Y16HPwsA57ebfabd80f9

新生代:

1.所有新对象创建发生在Eden区,Eden区满后触发新生代上的minor GC,将Eden区和非空闲Survivor区存活对象复制到另一个空闲的Survivor区中。

2.永远保证一个Survivor是空的,新生代minor GC就是在两个Survivor区之间相互复制存活对象,直到Survivor区满为止。

旧生代:

1.Eden区满后触发minor GC将存活对象复制到Survivor区,Survivor区满后触发minor GC将存活对象复制到旧生代。

2.经过新生代的两个Survivor之间多次复制,仍然存活下来的对象就是年龄相对比较老的,就可以放入到旧生代了,随着时间推移,如果旧生代也满了,将触发Full GC,针对整个堆(有新生代、旧生代和持久代)进行垃圾回收。

持久代:

持久代如果满,将触发Full GC

1.2 垃圾回收

要执行gc关键在于两点,一是检测垃圾对象,二是释放垃圾对象所占用的空间。

1.2.1 检测垃圾对象

检测出垃圾对象一般有两种算法

1、 引用计数法

2、 可达性分析

引用计数法因为无法检测对象之间相互循环引用的问题,基本没有被采用。现在主流的语言的垃圾收集中检测垃圾对象主要还是“可达性分析”方法,下面也主要介绍JVM可达性分析方法检测垃圾对象。

“可达性分析”算法描述?

通过一系列的名为“GC Root”的对象作为起点,从这些节点向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Root没有任何引用链相连时,则该对象不可达,该对象是不可使用的,垃圾收集器将回收其所占的内存。所以JVM判断对象需要存活的原则是:能够被一个根对象到达的对象。

什么是能够到达呢?

就是对象A中引用了对象B,那么就称A到B可达

GCRoot对象集合?

a.Java虚拟机栈(栈帧中的本地变量表)中的引用的对象。

b.方法区中的类静态属性引用的对象。

c.方法区中的常量引用的对象。

d.本地方法栈中JNI本地方法的引用对象。

1.2.2 释放空间1、垃圾回收算法

前面已经介绍了如何检测出垃圾对象,在检测出垃圾对象之后,需要按照特定的垃圾回收算法进行内存回收,常见的垃圾回收算法有:

u  复制(Copying)

u  标记-清除(Mark-Sweep)

u  标记-整理(Mark-Compact)

u  分代(Generational Collection),借助前面三种算法实现

这里就不一一详述,感兴趣可以自行百度。


  • 发表于 2016-09-29 01:11
  • 阅读 ( 468 )

0 条评论

请先 登录 后评论
小A
小A

29 篇文章

作家榜 »

  1. shitian 662 文章
  2. 石天 437 文章
  3. 每天惠23 33 文章
  4. 小A 29 文章