深入理解java虚拟机第三章笔记

第三章 垃圾收集器与内存分配策略

程序计数器,虚拟机栈,本地方法栈这三个区域随线程而生,随线程而灭,栈中的栈帧随着方法的进入和退出而有条不紊的执行入栈和出栈操作,每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的。因此这几个区域不需要过多考虑回收的问题。而java堆和方法区的内存的分配都是动态的,故需要关注这一部分的内存回收。

一 判断对象是否已死

引用计数算法:

用于判断对象是否存活的一种方式,给对象添加一个引用计数器,被引用时计数器加1,引用失效计数器减1,计数器为0则对象不再使用。但在java中不使用,原因是很难解决对象之间相互循环引用的问题。

在java中如果两个对象互相引用,但这两个对象已经不会再被访问,则这两个对象会被回收。

可达性分析算法:(主流语言使用)

通过一系列的“GC Roots”的对象作为起始点向下搜索,当一个对象到“GC Roots”没有任何引用链相连,则此对象不可用

java中,可作为“GC Roots”的对象包括:

*虚拟机栈(栈帧中的本地变量表)中引用的对象
*方法区中类静态属性引用的对象
*方法区中常量引用的对象

*本地方法栈中JNI(Native方法)引用的对象

关于引用的强度:强引用,软引用,弱引用,虚引用,引用强度逐渐减弱。

对象真正的死亡过程:即时在可达性分析算法中不可达的对象,也并非立刻死亡。一个对象死亡,要经历这样的过程:当没有引用时,会被进行第一次标记,并且筛选,筛选的条件是此对象是否有必要执行finalize方法,此方法最多被调用一次。没有覆盖或者已经执行过此方法的对象都是没有必要执行的。需要执行的会执行并进行第二次标记,此时有可能逃脱回收的范围。

方法区的回收:(或者HotSpot中的永久代1.8之前)主要回收废弃常量和无用的类。判断一个类无用:该类所有实例已被回收;加载该类的ClassLoader已经被回收;class对象没有被引用,无法通过反射访问该类的方法。

二 垃圾收集算法

1. 标记清除算法:首先标记所有需要回收对象,在标记完成后统一清除。标记过程和上面所述一样。效率低,清除后空间碎片多。

2. 复制算法:

因为年轻代中的对象基本都是朝生夕死的(80%以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。(为什么要有两块Survivor区来回复制,因为效率高,内存复制非常快)

在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。

3. 标记整理算法(用于老年代)

标记:它的第一个阶段与标记/清除算法是一模一样的,均是遍历GC Roots,然后将存活的对象标记。

整理:移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收。

4. 分代收集算法:将前面三种方法根据“代”的不同而使用不同的算法。

三 垃圾收集算法实现 

1. 枚举根节点 

通过OopMap记录这些位置(循环的末尾/方法临返回前/调用方法的call指令后/可能抛异常的位置)存放着对象引用从而快速完成GC Roots枚举

2. 安全点     

这些位置叫做安全点.我们在做GC的时候需要让jvm停在某个时间点上,如果不是这样,我们在分析对象间的引用关系的时候,引用关系还在不断的变化。这样我们的准确性就无法得到保证。 安全点就是所有的线程在要GC的时候停顿的位置。

3. 安全区域

有这样一类情况程序不能及时响应GC触发事件,比如sleep,因系统调用阻塞。 这些操作不是JVM能够控制的。JVM在此期间不能够响应GC事件。 因此,我们引入了安全区域的概念来解决这个问题。安全区域是其中引用不会改变的一段代码片段,那么在其中任一点进行根枚举都是安全的。 换句话说,安全区域是安全点的一个很大的扩展。在安全点的设计中,如果GC触发事件发生了,执行函数通过轮询进行响应。它通过设置一个准备好的标志(ready flag)来响应。 那么GC就可以进行根枚举了。这是一个握手协议。安全区域也遵循这个协议。执行函数在进入安全区域时设置ready flag。在它离开安全区域以前,它先检查GC是否完成了枚举(或者收集),并且不再需要执行函数呆在阻塞状态。如果是真的,它就向前执行,离开安全区域; 否则,它就像安全点一样阻塞他自己。

四 垃圾收集器

1.Serial收集器

单线程收集器,收集时必须暂停其他所有工作线程
虚拟机运行在Client模式下的默认新生代收集器

简单高效


2.ParNew收集器

Serial收集器多线程版本
许多运行在Server模式下虚拟机的默认新生代收集器

除了Serial收集器,只有它可以与CMS收集器配合工作


3.Parallel Scavenge收集器

新生代,使用复制算法,并行多线程收集器
此收集器目标是达到一个可控制的吞吐量(吞吐量=运行代码时间/(运行代码时间+垃圾收集时间))
适合在后台运算不需要太多交互的任务

具有自适应调节策略,根据当前运行情况动态调整参数

4.Serial Old收集器

Serial收集器老年代版本,单线程,使用标记-整理算法
这个收集器的主要也是在目前的JAVA的Client模式下的虚拟机使用。

如果在Server模式下,还有两大用途:一个是在JDK 1.5及之前的版本中与Parallel Scavenge收集器搭配使用,另外一个就是作为CMS收集器的后备预案。

5.Parallel Old收集器

Parallel Scavenge收集器老年代版本,多线程,标记-整理算法

6.CMS收集器(Concurrent Mark Sweep)

一种以获得最短回收停顿时间为目标的收集器
运行过程:初始标记,并发标记,重新标记,并发标记
初始标记仅仅只是标记GC Roots能直接关联到的对象,并发标记就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致的标记产生变动的那一部分标记记录。总体来说是和用户线程一起并发执行的

三个缺点:对CPU资源十分敏感;无法处理浮动垃圾,可能出现“Concurrent Mode Failure”而导致另一次Full GC 产生,这时启动后备预案:启动Serial Old收集器;基于标记-清除算法,收集结束可能会有大量空间碎片产生


7.G1收集器

一款面向服务端应用的垃圾收集器
具有分代收集,并行与并发,空间整合,可预测的停顿等特点
使用Region划分内存空间以及有优先级的区域回收方式

大致过程:初始标记,并发标记,最终标记,筛选回收

五 内存分配与回收策略

对象的内存分配,往大方向上讲,就是在堆上分配,对象的分配主要在新生代的Eden区,如果启动了本地线程分配缓冲,将按线程优先在TLAB(Thread Local Allocation Buffer,即线程本地分配缓存区)上分配。少数情况下也可能直接分配在老年代中。

1.对象优先在Eden分配

大多数情况下,对象在新生代Eden区中分配。当Eden没有足够空间分配时,虚拟机将发起一次Minor GC

2.大对象直接进入老年代

大对象是指需要大量连续内存空间的java对象,最典型的大对象就是很长的字符串以及数组。虚拟机提供了-XX:PretenureSizeThreshold参数,大于这个值得对象将直接分配在老年代。

3.长期存活的对象将进入老年代

虚拟机给每个对象定义了一个对象年龄(Age)计数器。如果对象在Eden出生并经过一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并且对象年龄设为1。每经历一次Minor GC,年龄增加一岁,当年龄达到一定程度(默认15岁),会晋升到老年代中。对象晋升老年代的阈值可以通过-XX:MaxTenuringThreshold来设置。另外,如果在survivor空间中相同年龄所有对象大小总和大于空间的一半,年龄大于等于该年龄的就可以直接进入老年代。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值