1. 哪些内存需要回收?
堆,方法
程序计数器,虚拟机栈,本地方法栈3个区域随线程而生,随线程而灭,内存的回收具有确定性
2. 回收哪些对象?
引用计数法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器就增1,引用失效,减一 (循环引用的问题)
可达性分析算法:通过一系列的称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索走过的路径称为引引用链,当一个对象到GC Roots没有任何引用链相连时,该对象是不可用的,极为氪回收对象。
2.1.引用分类
强引用(Strong Reference):类似 “Object obj = new Object()”,只要强引用存在,垃圾收集器永远不会回收掉被引用的对象。
软引用(Strong Reference):当垃圾搜集器工作时,如果当前内存够,就不回收,反之回收
弱引用(Strong Reference):只要垃圾搜集器工作,就会被回收。被关联的对象只能生存到下一次垃圾收集发生前。
虚引用(Strong Reference):不能通过虚引用指向一个对象实例。唯一目的是在关联对象被回收的时候收到一个系统通知,一般和ReferenceQueue联合使用。
2.2. 对象死亡过程
真正判定一个对象死亡,要经历两次标记过程。
2.3 回收方法区(HotSpot虚拟机中的永久代)
回收内容:废弃常量和无用的类
3.垃圾回收算法
3.1标记-清除算法
过程:标记出需要回收的对象,在标记完成后统一回收被标记的对象,
缺点:效率低,内存碎片
3.2复制算法 适用于存活率较低的时候
将内存分为大小相等的两块,每次只使用其中一块。当这一块的内存用完了就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
3.3标记-整理算法 适用于存活率较高的时候
标记出需要回收的对象,在标记后,将所有存货的对象都向一端移动,然后直接清理掉端边界以外的内存
3.4 分代收集算法
根据对象存活周期的不同将内存划分为几块,再根据各年代的特点采用最适当的收集算法。
在新生代中,对象存活率较低,可以采用复制算法
在老生代中,对象的存活率较高,可以采用标记-清除或者标记-整理
4.HotSpot的算法实现
4.1枚举根节点
4.2安全点
4.3 安全区域
5. 垃圾收集器
https://blog.csdn.net/tjiyu/article/details/53983650
6. 内存的分配和回收策略
名词解释:
VM区域总体分两类,heap区和非heap区。
heap区又分为:
Eden Space(伊甸园)、
Survivor Space(幸存者区)、有两个,其中一个一定为空
Old Gen(老年代)。
Minor GC :新生代垃圾收集动作,出现频繁,回收速度快
Major GC /Full GC:发生在老年代GC,至少会包括一次Minor GC,速度比Minor GC慢十倍左右
非heap区又分:
Code Cache(代码缓存区);
Perm Gen(永久代);
Jvm Stack(java虚拟机栈);
Local Method Statck(本地方法栈);
内存分配规则:
- Eden:Survivor From : Survivor To = 8:1:1
- Eden + Survivor = 新生代
- java堆 = 新生代内存 + 老年代内存
内存分配过程:
- 大多数情况下,对象在新生代Eden区分配,大对象(需要大量连续内存空间的java对象如数组,字符串)直接进入老年代
- 当Eden区没有足够的空间分配,虚拟机发起一次Minor GC(采用复制算法)
- Eden区域不能被回收的对象被放入到空的survivor(也就是To Survivor,同时Eden区域的内存会在垃圾回收的过程中全部释放),另一个survivor(即From Survivor)里不能被回收的对象也会被放入这个survivor(即To Survivor),然后To Survivor 和 From Survivor的标记会互换,始终保证一个survivor是空的。
- Survivor区中每“熬过”一次Minor GC,年龄就+1,当年龄到达一定的程度(默认15岁),就会被晋升到老年代Old Gen 中。
- 当老年代被放满的之后,虚拟机会进行垃圾回收,称之为Major GC。由于Major GC除并发GC外均需对整个堆进行扫描和回收,因此又称为Full GC。
动态对象年龄判断:
如果在Survivor空间中相同年龄所有对象大小的总和>Survivor空间的一半,年龄>=该年龄的对象就可3e入老年代
空间分配担保: