垃圾收集(GC)
Garbage Collection需要完成的事情:
1.哪些内存需要回收?
2.什么时候回收?
3.如何回收?
如何判断对象可以回收
1.引用计数算法(Reference Counting):
给对象添加一个引用计数器,每当有一个地方引用它时,计数器就+1,当引用失效时,计数器-1。当计数器为0时表示该对象不再被引用。
优点:实现简单、判断效率高
缺点:很难解决对象之间循环引用的问题
2.可达性分析算法(Reachability Analysis):
通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有使用任何引用链时,则说明该对象是不可用的。
优点:更加精确和严谨,可以分析出循环数据结构相互引用的情况
缺点:实现比较复杂、需要分析大量数据,消耗大量时间、分析过程需要GC停顿
Java语言中,可以作为GC Roots的对象包括如下几种:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(即一般说的Native方法)应用的对象
垃圾收集算法
标记-清除算法(Mark-Sweep)
优点:是最基础的收集算法
缺点:效率不高,产生内存碎片
复制算法(Copying)
优点:
实现简单,效率高。解决了标记-清除算法导致的内存碎片问题
缺点:
代价太大,将内存缩小了一半
商业虚拟机采用这钟算法回收新生代。
HotSpot虚拟机默认比例:
Eden:From:To = 8:1:1
当Survivor空间不足时依赖其他内存进行分配担保(Handler Promotion)
标记-整理算法(Mark-Compact)
优点:
不会产生内存碎片
缺点:
效率更低
分代收集算法(Generational Collection)
对象首先分配在Eden区
新生代空间不足时,触发Minor GC(该GC会触发Stop-The-World),伊甸园和幸存区From存活的对象复制到To区,存活的对象年龄+1,并且交换From和To的位置,当年龄达到一定程度时,则晋升至老年代
当老年代空间不足时,会先触发Minor GC,如果空间依旧不足,则触发Full GC, Stop-The-World时间更长