判断对象死没死
引用计数
应该都知道,引用一次+1,但是针对相互应用就无法计算了
可达性分析算法
引用的其他方式
在JDK 1.2之后,Java 对引用的概念进行了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference) 4种
强引用(Strong Reference)
Object obj=new Object();
软引用(Soft Reference)
将要发生内存溢出异常之前,将会把对象列入回收范围内,如果内存还是不足,才会抛出内存异常
弱引用(Weak Reference)
无论内存是否足够,发生垃圾回收,就会回收掉
虚引用(Phantom Reference)
回收时,能收到一个通知
是否让对象或者
死之前会调用finalize()方法
死之前引用会自救
这个东西建议忘掉,不确定太大
回收方法区
- 方法区主要存放永久代对象
- 方法区垃圾收集性价比较低
- 回收废弃常量和无用的类
类的卸载条件很多,需要满足以下三个条件*该类所有的实例都已经被回收,此时堆中不存在该类的任何实例。
加载该类的 ClassLoader 已经被回收。
该类对应的 Class 对象没有在任何地方被引用,也就无法在任何地方通过反射访问该类方法。
垃圾回收算法
标记-清除算法
复制算法
标记-整理算法
分代收集算法
现在的商业虚拟机采用分代收集算法,它根据对象存活周期将内存划分为几块,不同块采用适当的收集算法。
一般将堆分为新生代和老年代。
新生代使用:复制算法
老年代使用:标记 - 清除 或者 标记 - 整理 算法
枚举根节点
方法区有数百兆,不可能一个一个扫描,而且这东西必须在一个快照中进行,不能边扫描对象边变化吧。
所以虚拟机使用OopMap的数据结构,存哪些位置上有对象引用
安全点
并不是所有地方都存OopMap,那样就太多了,只是在特定的地点存,这就叫安全点
Gc 发生时,要保证线程在安全点上
抢先式中断
Gc 发生时,把所有线程中断,没有跑到安全点的,恢复线程,让他跑到安全点
主动式中断
线程自己轮询标志位,发现中断信号,自动跑到安全点停住
安全区域
当线程进入Sleep状态时,线程无法响应中断请求,他就进入安全区,必须等GC过程完成时,他才可以运行,否则一直等待
垃圾收集器
serial收集器
- 单线程
- 客户端比较好
- 暂停所有线程
ParNew收集器
- 和Serial收集器差不多,代码也有共用的地方,就是变成多线程了
- 多线程
- 服务器端比较好
Parallel Scavenge收集器
- 可以精确控制吞吐量,吞吐量=运行用户代码时间/(运行用户代码时间+垃圾手机时间)
- 可以自动调节(新生代,Eden和Survivor比例等细节参数)
Serial Old收集器
- 老年代
- 单线程
- 使用标记-整理
- 主要在Client下使用
- 在Server使用会搭配 Parallel Scavenge
Parallel Old收集器
- 老年代
- 使用多线程
- 标记-整理
CMS收集器
分为以下四个流程:
- 初始标记:仅仅只是标记一下 GC Roots 能直接关联到的对象,速度很快,需要停顿。
- 并发标记:进行 GC Roots Tracing 的过程,它在整个回收过程中耗时最长,不需要停顿。
- 重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,需要停顿。
- 并发清除:不需要停顿。
优点:
在整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,不需要进行停顿。
具有以下缺点:
-
吞吐量低:低停顿时间是以牺牲吞吐量为代价的,导致 CPU 利用率不够高。
-
无法处理浮动垃圾,可能出现 Concurrent Mode Failure。浮动垃圾是指并发清除阶段由于用户线程继续运行而产生的垃圾,这部分垃圾只能到下一次 GC 时才能进行回收。由于浮动垃圾的存在,因此需要预留出一部分内存,意味着 CMS 收集不能像其它收集器那样等待老年代快满的时候再回收。如果预留的内存不够存放浮动垃圾,就会出现 Concurrent Mode Failure,这时虚拟机将临时启用 Serial Old 来替代 CMS。
-
标记 - 清除算法导致的空间碎片,往往出现老年代空间剩余,但无法找到足够大连续空间来分配当前对象,不得不提前触发一次 Full GC。
G1 收集器
堆被分为新生代和老年代,其它收集器进行收集的范围都是整个新生代或者老年代,而 G1 可以直接对新生代和老年代一起回收。
G1 把堆划分成多个大小相等的独立区域(Region),新生代和老年代不再物理隔离。
内存分配与回收策略
Minor GC 和 Full GC
Minor GC:回收新生代,因为新生代对象存活时间很短,因此 Minor GC 会频繁执行,执行的速度一般也会比较快。
Full GC:回收老年代和新生代,老年代对象其存活时间长,因此 Full GC 很少执行,执行速度会比 Minor GC 慢很多。