GC算法
1跟踪回收
定期运行来检查垃圾,需要较长时间的中断。
2复制收集
复制收集的方式只需要对对象进行一次扫描。准备一个「新的空间」,从根开始,对对象进行扫,如果存在对这个对象的引用,就把它复制到「新空间中」。一次扫描结束之后,所有存在于「新空间」的对象就是所有的非垃圾对象。
3计数引用
针对每一个对象,保存一个对该对象的引用计数,该对象的引用增加,则相应的引用计数增加。如果对象的引用计数为零,则回收该对象。
缺点:循环引用的对象 标记的都不会为0所以。一直无法清除
在并行垃圾回收中不适合用,因为同步操作可能会对一个对象进行多次修改。
4标记清除
扫描到的对象如果是引用的对象那么就是被标记的,不是垃圾。
反之
以上都是基础算法。还附加衍生的算法:增量并行回收算法。一共三种
垃圾回收有几类:
1、串行垃圾回收器
串行垃圾回收器通过持有应用程序所有的线程进行工作。它为单线程环境设计,只使用一个单独的线程进行垃圾回收,通过冻结所有应用程序线程进行工作,所以可能不适合服务器环境。它最适合的是简单的命令行程序。
通过JVM参数-XX:+UseSerialGC
可以使用串行垃圾回收器。
2、并行垃圾回收器
并行垃圾回收器也叫做 throughput collector 。它是JVM的默认垃圾回收器。与串行垃圾回收器不同,它使用多线程进行垃圾回收。相似的是,它也会冻结所有的应用程序线程当执行垃圾回收的时候
3、并发标记扫描垃圾回收器
并发标记垃圾回收使用多线程扫描堆内存,标记需要清理的实例并且清理被标记过的实例。并发标记垃圾回收器只会在下面两种情况持有应用程序所有线程。
- 当标记的引用对象在tenured区域;
- 在进行垃圾回收的时候,堆内存的数据被并发的改变。
相比并行垃圾回收器,并发标记扫描垃圾回收器使用更多的CPU来确保程序的吞吐量。如果我们可以为了更好的程序性能分配更多的CPU,那么并发标记上扫描垃圾回收器是更好的选择相比并发垃圾回收器。
通过JVM参数 XX:+USeParNewGC
打开并发标记扫描垃圾回收器。
4、G1垃圾回收器
G1垃圾回收器适用于堆内存很大的情况,他将堆内存分割成不同的区域,并且并发的对其进行垃圾回收。G1也可以在回收内存之后对剩余的堆内存空间进行压缩。并发扫描标记垃圾回收器在STW情况下压缩内存。G1垃圾回收会优先选择第一块垃圾最多的区域
通过JVM参数 –XX:+UseG1GC
使用G1垃圾回收器
OOM的异常:
原因:
1堆内存的OOM异常:
堆内存用于存储实例对象,当我们不断创建对象,并且对象都有引用指向(GC Roots到对象之间有可达路径),那么垃圾回收机制就不会清理这些对象,当对象多到挤满堆内存的上限后,就产生OOM异常。
2JVM栈和本地方法栈的OOM异常:
a)StackOverFlowError
当线程请求的栈深度大于虚拟机所允许的最大栈深度,就会抛出这个异常。
b)OutOfMemeoryError
当虚拟机要扩展栈时无法申请到足够空间的内存,就会抛出这个异常。
内存泄漏导致的OOM:new出来的很多对象已经不需要了,但仍然有引用指向,所以垃圾回收机制无法回收。
3方法区的OOM异常
a)如何产生?
方法区中存放的是Class的相关信息,如:类名、访问修饰符、常量池、字段描述、方法描述等。
如果产生大量的类就有可能将方法区填满,从而产生方法区的OOM异常。