什么是垃圾回收机制
垃圾回收机制就是,不定时,向堆内存中清理不可达对象。
垃圾回收可以有效的防止内存泄漏,有效的使用空闲的内存。
内存泄漏是指改内存空间使用完毕之后未被回收,在不涉及复杂数据结构的一般情况下,java的内存泄漏表现为一个内存对象的生命周期超出了程序需要它的时间长度,我们优势也将其称为”对象游离“。
内存泄漏的定义:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着。
手动GC回收
public class JVMDemo {
public static void main(String[] args) {
JVMDemo jd = new JVMDemo();
jd = null;
System.gc();
}
protected void finalize() throws Throwable {
System.out.println("垃圾回收之前调用");
}
}
垃圾回收机制算法
1.引用计数法
每个对象都会有一个标记,默认是15次,gc回收时,对象现在不可达减去1 可达加上1
给对象中天添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,当引用失效时,计数器值就减一,任何时刻计数器为0的对象就是不在被使用的,垃圾收集器将回收改对象使用的内存。
优点:引用计数收集器可以很快的执行,交织在程序运行中,对程序需要不被长时间打断的实时环境比较有利
缺点:无法检测出循环引用,如对象有一个子对象的引用,子对象反过来引用父对象,这样他们的引用计数永远不可能为0,而且每次加减非常浪费内存。
2.复制算法
复制算法用于在新生代垃圾回收。
s0和s1将可用内存按容量分成大小相等的两块,每次只使用其中一块,当这块内存使用完了,就将还存活的对象复制到另一块内存上去,然后把使用过的内存空间一次清理掉,这样使得每次都是对其中一块内存进行回收。
优点:不用考虑内存碎片复杂情况,只需要移动堆顶指针。
缺点:内存将为原来一半
3.标记清除算法
主要就是两个动作,一个是标记,一个就是清除。标记出内存中那些对象可以回收,那些对象还要继续用。
缺点:标记与清除没有连续性效率低,清除之后内存会产生大量碎片。
4.标记压缩算法
标记压缩法在标记清除基础上做了优化,把存活的对象压缩到内存一端,而后进行垃圾清理.
老年代使用的就是标记压缩法。
5.分代收集算法
根据内存中对象的存活周期不同,将内存划分为几块,java的虚拟机中一般把内存划分为新生代和老年代。
垃圾回收时停顿现象
垃圾回收的任务是识别和回收垃圾对象进行内存清理,为了让垃圾回收器可以更高效的执行,大部分情况下,会要求系统进入一个停顿的状态,停顿的目的就是为了终止所有的应用线程,只有这样的系统才不会有新的垃圾的产生。
垃圾回收器
java垃圾回收器是java虚拟机(jvm)的三个重要模块(另外两个是解释器和多线程机制)之一,为应用程序提供内存的自动分配,自动回收功能,这个两个操作都发生在java堆上。某一个时刻,一个对象如果有一个以以上的引用指向它,那么该对象就为活着的,否则死亡,视为垃圾,可被垃圾回收器回收在利用,来及回收操作需要消耗cpu,线程时间等资源,所以容易理解的是垃圾回收操作不是实时的发生,当内存消耗完活着是达到某一个指标时,触发垃圾回收操作。
串行回收器(Serial collector)
单线程执行回收操作,回收期间暂停所有应用线程的执行,client模式下的默认回收器,通过-XX:+UseSerialGC命令行可选项强制指定,参数可以设置使用新生代串行和老年代串行回收器。
年轻代的回收算法
把eden区的存活对象移到to区,to区装不下直接移到年老代,把from区的移到to区,to区装不下直接移到年老代,from区里面年龄很大的升级到年老代,回收结束之后,eden和from区都为空,此时把from和to的功能互换,from变to,to变from,每一轮回收之前to都是空的。
年老代的回收分为三个步骤,标记,清除,合并。标记阶段把所有存活的对象标记出来,清除阶段释放所有死亡的对象,合并阶段,把所有活着的对象合并到年老代的前部分,把空闲的片段都留到后面。
并行回收器(Parnew回收器)
并行回收器在串行回收器的基础上做了改进,他可以使用多个线程同时进行垃圾回收,对于计算能力强的计算机而言,可以有效的缩短垃圾回收所需的时间。
ParNew回收器是一个工作在新生代的垃圾收集器,他只是简单的将串行回收器多线程快速的回收策略和算法和串行回收器一样
使用XX:+UseParNewGC新生代ParNew回收器,老年代则使用并行回收器ParNew回收器工作时的线程数量可以使用XX:ParaleiGCThreads参数指定,一般最好和计算机的CPU相当,避免过多的线程影响性能。
并行回收器(ParallelGC)
老年代ParallelOldGC回收器也是一种多线程的回收器,和新生代的ParallelGC回收器一样,也是一种关住吞吐量的回收器,他使用了标记压缩算法进行实现。
-XX:+UseParallelOldGC进行设置
-XX:+ParallelCThread也可以设置垃圾收集时的线程数量。
并CMS回收器
cms收集器是一种以获取最短回收停顿时间为目标的收集器,cms收集器是基于标记-清除算法实现的,整个收集过程大致分为4个步骤
初始标记->并发标记->重新标记->并发清除
G1回收器
G1回收器jdk1.7中提出的垃圾回收器,从长期目标来看是为了取代cms回收器,G1回收器拥有独特的垃圾回收策略,G1属于分代垃圾回收器,区分新生代和老年代,依然有eden和from/to区,它并不要求整个eden区或者新生代,老年代的空间都连续,它使用了分区算法。
并行性:G1回收器期间可多线程同时工作
并发性G1拥有与应用程序交换执行能力,部分工作可与应用程序同时执行,在整个GC期间不会完全阻塞应用程序。
使用XXX:+UseG1GC应用G1收集器
Mills指定最大停顿时间
使用-XX:MaxGCPausel
设置并行回收的线程数量
使用-XX:ParallelGCThreads
//串行吞吐量
//最大内存512,初始内存512
-XX:+PrintGCDetails -Xmx512M -Xms512M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseSerialGC
-XX:PermSize=32M
//并行回收(UseParNewGC)
//最大内存512,初始内存512
-XX:+PrintGCDetails -Xmx512M –Xms512M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseParNewGC
-XX:PermSize=32M
//并行合并回收(UseParallelGC)
//最大内存512,初始内存512
-XX:+PrintGCDetails -Xmx512M -Xms512M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseParallelGC
-XX:+UseParallelOldGC
-XX:ParallelGCThreads=8
-XX:PermSize=32M
调优总结
初始堆值和最大堆内存内存越大,吞吐量就越高。
最好使用并行收集器,因为并行回收器速度比串行吞吐量高,速度快。
设置堆内存新生代的比例和老年代的比例最好为1:2或者1:3
减少GC对老年代的回收。