1、如何判断对象不可用
判断对象不可用有2个算法:引用计数法、可达性分析算法
引用计数法:给对象添加一个引用计数器当计数为0是说明对象不在被引用。
优点:操作简单、方便实现。
缺点:无法解决对象相互引用的问题
可达性分析算法:当对象到GC ROOTS没有连接,证明对象不可用。但是当对象的finalize()方法被重写重新与GC ROOTS连接那么对象会变成可达对象;若没重写方法就会被回收。一个对象finalize()方法只会被调用一次。
2、GC ROOTS有哪些
- 在虚拟机栈中的引用对象
- 在方法区中类静态属性引用的对象
- 在方法区中常量引用的对象
- 在本地方法栈中JNI引用的对象
- Java虚拟机内部的引用
- 所有被同步锁持有的对象
3、 GC 算法
GC有3种算法:标记清除算法、复制算法、标记整理算法
标记清除算法:将在使用的对象标记,清除未被标记的对象。
复制算法:幸存者区的复制(from - to);每次GC将伊甸园的存活对象放到幸存者中,幸存者有2个区域谁空谁是被复制的区域。
标记整理算法:先执行标记清除算法,然后在整理,将内存碎片移动到一端。
算法 | 优点 | 缺点 |
标记清除 | 效率快 | 内存碎片 |
复制算法 | 没有内存的碎片 | 占用空间 |
标记整理 | 内存整齐 | 效率低 |
4、GC 回收器
Serial GC/Serialold GC:串行回收(单线程)和STW机制,SerialGC采用复制算法,用于新生代的垃圾回收;SerialoldGC采用标记-整理算法,用于老年代的垃圾回收;
ParNewGC:并行回收(多线程)和STW机制,只适用于新生代的垃圾回收,采用复制算法;
ParallelScavenge GC/Parallelold GC(吞吐量优先):并行回收和STW机制,ParallelScavenge采用复制算法,用于新生代的垃圾回收;Parallelold采用标记-整理算法,用于老年代垃圾回收;Parallel与ParNew的区别在于自适应调节策略;
CMS(ConcurrentMarkSweep)(低延迟):并发回收,GC线程与用户线程同时进行,采用标记-清除算法,用于老年代的垃圾回收;
CMS四个阶段:
1.初始标记阶段:STW机制,主要任务只是标记出与GCroots直接关联的对象,这个过程耗时很短;
2.并发标记阶段:从与GCroots直接关联的对象开始向下搜索,标记出所有的关联对象,这个过程耗时很长,但不妨碍用户线程的继续执行;
3.重新标记阶段:STW机制,主要目的是为了修正并发标记期间,因用户程序的继续运作而导致标记对象产生变动的部分;
4.并发清除阶段:清除标记阶段识别的不可达对象,释放内存空间;
回收器 | 分类 | 作用位置 | 使用算法 | 特点 |
serial | 串行运行 | 新生代 | 复制算法 | 响应速度快 |
ParNew | 并行运行 | 新生代 | 复制算法 | 响应速度快 |
Parallel | 并行运行 | 新生代 | 复制算法 | |
serial Old | 串行于行 | 老年代 | 标记整理 | 响应速度快 |
Parallel Old | 并行运行 | 老年代 | 标记整理 | |
CMS | 并发运行 | 老年代 | 标记清除 | 响应速度快 |
G1 | 并行、并发运行 | 不分代(分区) | 标记整理、复制 | 响应速度快 |
jdk1.7 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.9 默认垃圾收集器G1
内存溢出:实实在在的内存空间不足导致;
内存泄漏:该释放的对象没有释放,多见于自己使用容器保存元素的情况下。